Yii2 init 初始化脚本分析

脚本目的:

init 脚本主要的作用是:从 environments 目录中复制配置文件,确保应用适配不同环境(例如开发、生产环境等)。

工作流程:

  • 获取 $_SERVERargv 参数

  • 加载 environments/index.php 文件,拿到不同环境配置指定的配置文件关系。

  • 如果执行 init 脚本时提供了 --env 选项,例如:--env=Development 则直接应用此环境,否则会被提示需要选择一个环境来初始化。

  • 获取 environments 对应环境下的所有文件。

  • 因为上一步获取到的所有文件是带有文件全路径的,所以这一步直接复制文件到对应的路径,如:frontend/config/params-local.php

  • environments/index.php 文件中获取到对应环境所配置的需要设置可写、可执行的目录来执行操作。

代码详解:

  • 解析命令行参数:
  • 检查命令行参数:
  • 获取 environments 中的文件列表:
  • 复制文件:
php 复制代码
function copyFile($root, $source, $target, &$all, $params)
{
    // 检查源文件是否存在
    if (!is_file($root . '/' . $source)) {
        echo "       skip $target ($source not exist)\n";
        return true;
    }
    // 检查目标文件是否存在
    if (is_file($root . '/' . $target)) {
        if (file_get_contents($root . '/' . $source) === file_get_contents($root . '/' . $target)) {
            echo "  unchanged $target\n";
            return true;
        }
        // 如果$all为true,输出信息并直接进行覆盖。
        // 否则,提示用户目标文件已存在,并询问是否覆盖(选择"是"、"否"、"全部"或"退出")。
        if ($all) {
            echo "  overwrite $target\n";
        } else {
            echo "      exist $target\n";
            echo "            ...overwrite? [Yes|No|All|Quit] ";


            // 通过命令行接收用户输入。如果$params['overwrite']不为空,使用该值;否则,等待用户输入。
            $answer = !empty($params['overwrite']) ? $params['overwrite'] : trim(fgets(STDIN));

            // 根据用户输入执行相应操作:
            // 如果输入"q"或"Q",返回false以退出操作。
            // 如果输入"y"或"Y",输出覆盖信息并继续。
            // 如果输入"a"或"A",输出覆盖信息并设置$all为true,以便后续文件均自动覆盖。
            // 其他输入则跳过目标文件。
            if (!strncasecmp($answer, 'q', 1)) {
                return false;
            } else {
                if (!strncasecmp($answer, 'y', 1)) {
                    echo "  overwrite $target\n";
                } else {
                    if (!strncasecmp($answer, 'a', 1)) {
                        echo "  overwrite $target\n";
                        $all = true;
                    } else {
                        echo "       skip $target\n";
                        return true;
                    }
                }
            }
        }
        file_put_contents($root . '/' . $target, file_get_contents($root . '/' . $source));
        return true;
    }
    // 如果目标文件不存在,输出信息并进行复制。
    echo "   generate $target\n";
    // 使用@mkdir创建目标文件的目录(如果不存在),并设置目录权限为0777。
    @mkdir(dirname($root . '/' . $target), 0777, true);
    file_put_contents($root . '/' . $target, file_get_contents($root . '/' . $source));
    return true;
}
  • 执行回调方法:
php 复制代码
$callbacks = ['setCookieValidationKey', 'setWritable', 'setExecutable', 'createSymlink'];
foreach ($callbacks as $callback) {
    if (!empty($env[$callback])) {
        $callback($root, $env[$callback]);
    }
}
// 读取 environments/index.php 文件的配置:
'Development' => [
    'path' => 'dev',
    'setWritable' => [ // runtime目录设置为可写
        'backend/runtime',
        'console/runtime',
        'frontend/runtime',
    ],
    'setExecutable' => [ // yii、yii_test文件设置为可执行
        'yii',
        'yii_test',
    ],
    'setCookieValidationKey' => [
        'backend/config/main-local.php',
        'common/config/codeception-local.php',
        'frontend/config/main-local.php',
    ],
],

// 执行具体的回调方法:
// 设置文件可写
function setWritable($root, $paths)
{
    foreach ($paths as $writable) {
        if (is_dir("$root/$writable")) {
            if (@chmod("$root/$writable", 0777)) {
                echo "      chmod 0777 $writable\n";
            } else {
                printError("Operation chmod not permitted for directory $writable.");
            }
        } else {
            printError("Directory $writable does not exist.");
        }
    }
}

// 设置文件可执行
function setExecutable($root, $paths)
{
    foreach ($paths as $executable) {
        if (file_exists("$root/$executable")) {
            if (@chmod("$root/$executable", 0755)) {
                echo "      chmod 0755 $executable\n";
            } else {
                printError("Operation chmod not permitted for $executable.");
            }
        } else {
            printError("$executable does not exist.");
        }
    }
}

function setCookieValidationKey($root, $paths)
{
    foreach ($paths as $file) {
        echo "   generate cookie validation key in $file\n";
        $file = $root . '/' . $file;
        $length = 32;
        $bytes = openssl_random_pseudo_bytes($length);
        $key = strtr(substr(base64_encode($bytes), 0, $length), '+/=', '_-.');
        $content = preg_replace('/(("|\')cookieValidationKey("|\')\s*=>\s*)(""|\'\')/', "\\1'$key'", file_get_contents($file));
        file_put_contents($file, $content);
    }
}
相关推荐
两个人的幸福12 天前
Windows 桌面应用自研 PHP 队列(下):完整代码与六大工程化优化
php
BingoGo14 天前
PHP 泛型之殇 泛型 RFC 提案被拒绝
后端·php
JaguarJack14 天前
PHP 泛型之殇 泛型 RFC 提案被拒绝
后端·php
用户30745969820715 天前
PHP 扩展——从入门到理解
php
鹏仔先生15 天前
拷贝漫画APP下载页PHP程序,后台带免费AI写作
php
云水一下15 天前
从零开始学 PHP 系列(一):PHP 的前世今生与开发环境搭建
开发语言·php
xingpanvip16 天前
星盘接口开发文档:本命盘接口指南
android·开发语言·css·php·lua
酉鬼女又兒16 天前
零基础入门计算机网络运输层:端到端通信核心作用、端口号分类规则、复用分用工作机制及UDP与TCP协议全方位对比详解
网络·网络协议·tcp/ip·计算机网络·考研·udp·php
dog25016 天前
不要再继续优化 TCP
网络协议·tcp/ip·php
Channing Lewis16 天前
PHP 解析 Excel 的那些坑:一次“行号错位”引发的数据丢失
开发语言·php·excel