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);
    }
}
相关推荐
CRMEB定制开发21 分钟前
CRMEB 中 PHP 快递查询扩展实现:涵盖一号通、阿里云、腾讯云
阿里云·php·腾讯云·商城系统·商城源码
CRMEB定制开发1 小时前
PHP 打印扩展开发:从易联云到小鹅通的多驱动集成实践
php·小程序源码·商城源码·微信商城·php商城源码
Bruce_Liuxiaowei1 小时前
PHP文件包含漏洞详解:原理、利用与防御
开发语言·网络安全·php·文件包含
Bruce_Liuxiaowei5 小时前
深入理解PHP安全漏洞:文件包含与SSRF攻击全解析
开发语言·网络安全·php
痴人说梦梦中人11 小时前
自建 dnslog 回显平台:渗透测试场景下的隐蔽回显利器
web安全·网络安全·渗透测试·php·工具
我是老孙18 小时前
windows10 php报错
开发语言·php
小红帽2.021 小时前
开源PHP在线客服系统源码搭建教程
开发语言·开源·php
CRMEB定制开发1 天前
CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云
阿里云·php·腾讯云·微信商城·php商城源码
hao_wujing1 天前
攻击模型的恶意行为检测
网络·数据库·php
Yungoal2 天前
php & apache构建 Web 服务器
服务器·php·apache