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);
    }
}
相关推荐
damoluomu9 小时前
挑 PHP CMS 之前,先学会看它的协议
php
子非鱼a17 小时前
【WEB】Online ToolWEB
php
PHP实战开发录18 小时前
Nginx上传大文件为什么报413
nginx·php·开发
damoluomu1 天前
国产企业级 PHP CMS:哪些能免费商用
php
郑州光合科技余经理1 天前
同城外卖小程序开发:下单成功后,后台导出能不能对上用户端状态
开发语言·前端·git·后端·uni-app·php·ai编程
MyFreeIT1 天前
Android PHP Manual
php
aixingpan1 天前
aixingpan.cn API开发文档:api_docs_trichart_natal_progression_sec_transit2接口指南
前端·php
sbjdhjd2 天前
从日志包含到临时文件竞争:文件包含进阶复盘中的 Docker、Windows 与 Session 限制
网络·安全·web安全·网络安全·数据挖掘·php·rce
daxiangxm2 天前
【趣味休息】“围住小猫在线玩”-“困住小猫”,又回来了
数据结构·人工智能·vscode·github·php
星光开发者2 天前
基于Spring Boot的充电桩管理系统的设计与实现-计算机毕设【课程设计】57105
vue.js·spring boot·vscode·mysql·django·php·express