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);
    }
}
相关推荐
Ai 编码助手20 分钟前
使用php和Xunsearch提升音乐网站的歌曲搜索效果
开发语言·php
wkj0012 小时前
php操作redis
开发语言·redis·php
黑客Ash11 小时前
【D01】网络安全概论
网络·安全·web安全·php
->yjy11 小时前
计算机网络(第一章)
网络·计算机网络·php
阳光帅气男孩12 小时前
PhpSpreadsheet导出图片
php
周全全13 小时前
Spring Boot + Vue 基于 RSA 的用户身份认证加密机制实现
java·vue.js·spring boot·安全·php
Mr.Pascal14 小时前
刚学php序列化/反序列化遇到的坑(攻防世界:Web_php_unserialize)
开发语言·安全·web安全·php
建群新人小猿14 小时前
会员等级经验问题
android·开发语言·前端·javascript·php
黑客Ela17 小时前
网络安全问题概述
安全·web安全·php