如何讀取?如何保存?這是重點php
逐行正則匹配,一次不能多行。且只能定義
bool
/string
類型。laravel
getenv
: laravel的env是經過該函數獲取env環境變量 那麼存儲呢?使用了Dotenv包 加載以下:Dotenv\Loader類下:數據庫
/** * Load `.env` file in given directory. * * @return array */ public function load() { $this->ensureFileIsReadable(); $filePath = $this->filePath; $lines = $this->readLinesFromFile($filePath); foreach ($lines as $line) { if (!$this->isComment($line) && $this->looksLikeSetter($line)) { $this->setEnvironmentVariable($line); } } return $lines; }
說明加載env文件效率比較低。apache
順着getEnvironmentVariable
往下:bootstrap
public function setEnvironmentVariable($name, $value = null) { // 這裏就是解析了 list($name, $value) = $this->normaliseEnvironmentVariable($name, $value); // Don't overwrite existing environment variables if we're immutable // Ruby's dotenv does this with `ENV[key] ||= value`. if ($this->immutable && $this->getEnvironmentVariable($name) !== null) { return; } // If PHP is running as an Apache module and an existing // Apache environment variable exists, overwrite it if (function_exists('apache_getenv') && function_exists('apache_setenv') && apache_getenv($name)) { apache_setenv($name, $value); } if (function_exists('putenv')) { putenv("$name=$value"); } $_ENV[$name] = $value; $_SERVER[$name] = $value; }
上面的代碼會注意到:apache_getenv
和apache_setenv
和putenv
對於apche_getenv
: http://php.net/manual/zh/function.apache-setenv.php緩存
putenv
: 添加 setting 到服務器環境變量。 環境變量僅存活於當前請求期間。 在請求結束時環境會恢復到初始狀態。服務器
優勢:一、優雅 二、穩定性 先看他的優雅寫法:app
list($name, $value) = array_map('trim', explode('=', $name, 2));
對於穩定性: 上面設置了$_ENV
、$_SERVER
、putenv
這些都是爲了跨平臺的穩定性,若是其中一個變量不可用,就從另外一箇中獲取。ide
解析過程函數
/** *規範化給定的環境變量。 * *取得開發人員傳入的值和: * - 確保咱們處理單獨的名稱和值,若是須要,將名稱字符串分開,引號 * - 解析變量值, * - 解析帶有雙引號的變量名, * - 解析嵌套變量。 * * @param string $ name * @param string $ value * * @return array */ protected function normaliseEnvironmentVariable($name, $value) { // 就是簡單的 array_map('trim', explode('=', $name, 2)); 根據等號分開而且去除兩邊空格 list($name, $value) = $this->splitCompoundStringIntoParts($name, $value); // 解析淨化變量名 list($name, $value) = $this->sanitiseVariableName($name, $value); // 解析淨化變量值 這個是最複雜的部分 list($name, $value) = $this->sanitiseVariableValue($name, $value); $value = $this->resolveNestedVariables($value); return array($name, $value); } protected function sanitiseVariableName($name, $value) { // 支持 export方式定義變量,把單引號和雙引號去掉 $name = trim(str_replace(array('export ', '\'', '"'), '', $name)); return array($name, $value); } // protected function sanitiseVariableValue($name, $value) { $value = trim($value); if (!$value) { return array($name, $value); } if ($this->beginsWithAQuote($value)) { // value starts with a quote $quote = $value[0]; // 支持引號的方式定義環境變量 $regexPattern = sprintf( '/^ %1$s # match a quote at the start of the value ( # capturing sub-pattern used (?: # we do not need to capture this [^%1$s\\\\] # any character other than a quote or backslash |\\\\\\\\ # or two backslashes together |\\\\%1$s # or an escaped quote e.g \" )* # as many characters that match the previous rules ) # end of the capturing sub-pattern %1$s # and the closing quote .*$ # and discard any string after the closing quote /mx', $quote ); $value = preg_replace($regexPattern, '$1', $value); $value = str_replace("\\$quote", $quote, $value); $value = str_replace('\\\\', '\\', $value); } else { // 沒有引號 每一行的均可能有#註釋須要去掉 $parts = explode(' #', $value, 2); #相似這樣得註釋 $value = trim($parts[0]); // 區井號#前面的部分做爲值。這裏就須要注意了 // Unquoted values cannot contain whitespace 非引號包含的值,不能包含空格 if (preg_match('/\s+/', $value) > 0) { throw new InvalidFileException('Dotenv values containing spaces must be surrounded by quotes.'); } } return array($name, trim($value)); } // 是否包含單引號或者雙引號 protected function beginsWithAQuote($value) { return strpbrk($value[0], '"\'') !== false; }
使用php artisan config:cache
以後env
函數再也不有用,就是從getenv
沒法獲取數據?緣由?
由於cache
了以後,laravel
就會將全部config
生成緩存文件,而且判斷若是緩存文件生成,就不會加載.env
文件,所以env函數就不會獲取導數據啦,那麼是哪裏判斷了? \Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables
類在做怪!!
public function bootstrap(Application $app) { // 是否緩存config目錄的配置了,緩存了就不會去加載.env if ($app->configurationIsCached()) { return; } // 檢查env應該加載哪個文件 $this->checkForSpecificEnvironmentFile($app); try { // 這個時候才加載 .env (new Dotenv($app->environmentPath(), $app->environmentFile()))->load(); } catch (InvalidPathException $e) { // } }
這個加載環境變量是何時加載的? 看Kernel
內核代碼,laravel
的內核分爲console
和http
兩種。咱們固然看http
的。 \Illuminate\Foundation\Http\Kernel
類
protected $bootstrappers = [ \Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::class, \Illuminate\Foundation\Bootstrap\LoadConfiguration::class, \Illuminate\Foundation\Bootstrap\HandleExceptions::class, \Illuminate\Foundation\Bootstrap\RegisterFacades::class, \Illuminate\Foundation\Bootstrap\RegisterProviders::class, \Illuminate\Foundation\Bootstrap\BootProviders::class, ];
能夠看到,加載env變量是啓動的第一步,而後就是加載config目錄的文件。這些類都有一個叫bootstrap的方法。
一、.env
文件的變量有註釋功能 二、保存在請求期間的環境變量中 三、重點:在config:cache
以後不會加載env
,所以不能再config
目錄之外的文件使用env
函數,不然將會致使程序以超乎想象的方式運行。我相信你的程序多少會出現這個問題。 四、非引號包含的值,不能包含空格 五、值會去除井號#
後面部分保留前面部分,這就可能有問題了。好比:
# 數據庫密碼包含井號,那咋辦? # 錯誤 db_password=12345#%snq # 正確 使用引號 db_password="12345#%snq"
下一節就是閱讀LoadConfiguration
源碼了-config目錄的加載。