指令碼目的:
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);
}
}