腳本目的:
init 腳本主要的作用是:從 environments 目錄中複製配置文件,確保應用適配不同環境(例如開發、生產環境等)。
工作流程:
- 獲取
$_SERVER的argv參數 - 加載
environments/index.php文件,拿到不同環境配置指定的配置文件關係。 - 如果執行
init腳本時提供了--env選項,例如:--env=Development則直接應用此環境,否則會被提示需要選擇一個環境來初始化。 - 獲取
environments對應環境下的所有文件。 - 因為上一步獲取到的所有文件是帶有文件全路徑的,所以這一步直接複製文件到對應的路徑,如:
frontend/config/params-local.php。 - 從
environments/index.php文件中獲取到對應環境所配置的需要設置可寫、可執行的目錄來執行操作。
代碼詳解:
- 解析命令行參數:
- 檢查命令行參數:
- 獲取
environments中的文件列表:
- 複製文件:
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;
}
- 執行回調方法:
$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);
}
}