本篇文章给大家带来的内容是关于Laravel框架下ENV的加载和读取的介绍,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。
Laravel在启动时会加载项目中的.env文件。对于应用程序运行的环境来说,不同的环境有不同的配置通常是很有用的。 例如,你可能希望在本地使用测试的Mysql数据库而在上线后希望项目能够自动切换到生产Mysql数据库。本文将会详细介绍 env 文件的使用与源码的分析。
Env文件的使用
多环境env的设置
项目中env文件的数量往往是跟项目的环境数量相同,假如一个项目有开发、测试、生产三套环境那么在项目中应该有三个.env.dev、.env.test、.env.prod三个环境配置文件与环境相对应。三个文件中的配置项应该完全一样,而具体配置的值应该根据每个环境的需要来设置。
接下来就是让项目能够根据环境加载不同的env文件了。具体有三种方法,可以按照使用习惯来选择使用:
在环境的nginx配置文件里设置APP_ENV环境变量fastcgi_param APP_ENV dev;
设置服务器上运行PHP的用户的环境变量,比如在www用户的/home/www/.bashrc中添加export APP_ENV dev
在部署项目的持续集成任务或者部署脚本里执行cp .env.dev .env
针对前两种方法,Laravel会根据env('APP_ENV')加载到的变量值去加载对应的文件.env.dev、.env.test这些。 具体在后面源码里会说,第三种比较好理解就是在部署项目时将环境的配置文件覆盖到.env文件里这样就不需要在环境的系统和nginx里做额外的设置了。
自定义env文件的路径与文件名
env文件默认放在项目的根目录中,laravel 为用户提供了自定义 ENV 文件路径或文件名的函数,
例如,若想要自定义 env 路径,可以在 bootstrap 文件夹中 app.php 中使用Application实例的useEnvironmentPath方法:
$app = new Illuminate\Foundation\Application( realpath(__DIR__.'/../') ); $app->useEnvironmentPath('/customer/path')
若想要自定义 env 文件名称,就可以在 bootstrap 文件夹中 app.php 中使用Application实例的loadEnvironmentFrom方法:
$app = new Illuminate\Foundation\Application( realpath(__DIR__.'/../') ); $app->loadEnvironmentFrom('customer.env')
Laravel 加载ENV配置
Laravel加载ENV的是在框架处理请求之前,bootstrap过程中的LoadEnvironmentVariables阶段中完成的。
我们来看一下\Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables的源码来分析下Laravel是怎么加载env中的配置的。
<?php namespace Illuminate\Foundation\Bootstrap; use Dotenv\Dotenv; use Dotenv\Exception\InvalidPathException; use Symfony\Component\Console\Input\ArgvInput; use Illuminate\Contracts\Foundation\Application; class LoadEnvironmentVariables { /** * Bootstrap the given application. * * @param \Illuminate\Contracts\Foundation\Application $app * @return void */ public function bootstrap(Application $app) { if ($app->configurationIsCached()) { return; } $this->checkForSpecificEnvironmentFile($app); try { (new Dotenv($app->environmentPath(), $app->environmentFile()))->load(); } catch (InvalidPathException $e) { // } } /** * Detect if a custom environment file matching the APP_ENV exists. * * @param \Illuminate\Contracts\Foundation\Application $app * @return void */ protected function checkForSpecificEnvironmentFile($app) { if ($app->runningInConsole() && ($input = new ArgvInput)->hasParameterOption('--env')) { if ($this->setEnvironmentFilePath( $app, $app->environmentFile().'.'.$input->getParameterOption('--env') )) { return; } } if (! env('APP_ENV')) { return; } $this->setEnvironmentFilePath( $app, $app->environmentFile().'.'.env('APP_ENV') ); } /** * Load a custom environment file. * * @param \Illuminate\Contracts\Foundation\Application $app * @param string $file * @return bool */ protected function setEnvironmentFilePath($app, $file) { if (file_exists($app->environmentPath().'/'.$file)) { $app->loadEnvironmentFrom($file); return true; } return false; } }
在他的启动方法bootstrap中,Laravel会检查配置是否缓存过以及判断应该应用那个env文件,针对上面说的根据环境加载配置文件的三种方法中的头两种,因为系统或者nginx环境变量中设置了APP_ENV,所以Laravel会在checkForSpecificEnvironmentFile方法里根据 APP_ENV的值设置正确的配置文件的具体路径, 比如.env.dev或者.env.test,而针对第三中情况则是默认的.env, 具体可以参看下面的checkForSpecificEnvironmentFile还有相关的Application里的两个方法的源码:
protected function checkForSpecificEnvironmentFile($app) { if ($app->runningInConsole() && ($input = new ArgvInput)->hasParameterOption('--env')) { if ($this->setEnvironmentFilePath( $app, $app->environmentFile().'.'.$input->getParameterOption('--env') )) { return; } } if (! env('APP_ENV')) { return; } $this->setEnvironmentFilePath( $app, $app->environmentFile().'.'.env('APP_ENV') ); } namespace Illuminate\Foundation; class Application .... { public function environmentPath() { return $this->environmentPath ?: $this->basePath; } public function environmentFile() { return $this->environmentFile ?: '.env'; } }
判断好后要读取的配置文件的路径后,接下来就是加载env里的配置了。
(new Dotenv($app->environmentPath(), $app->environmentFile()))->load();
Laravel使用的是Dotenv的PHP版本vlucas/phpdotenv
class Dotenv { public function __construct($path, $file = '.env') { $this->filePath = $this->getFilePath($path, $file); $this->loader = new Loader($this->filePath, true); } public function load() { return $this->loadData(); } protected function loadData($overload = false) { $this->loader = new Loader($this->filePath, !$overload); return $this->loader->load(); } }
它依赖/Dotenv/Loader来加载数据:
class Loader { 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; } }
Loader读取配置时readLinesFromFile函数会用file函数将配置从文件中一行行地读取到数组中去,然后排除以#开头的注释,针对内容中包含=的行去调用setEnvironmentVariable方法去把文件行中的环境变量配置到项目中去:
namespace Dotenv; class Loader { public function setEnvironmentVariable($name, $value = null) { list($name, $value) = $this->normaliseEnvironmentVariable($name, $value); $this->variableNames[] = $name; // 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; } public function getEnvironmentVariable($name) { switch (true) { case array_key_exists($name, $_ENV): return $_ENV[$name]; case array_key_exists($name, $_SERVER): return $_SERVER[$name]; default: $value = getenv($name); return $value === false ? null : $value; // switch getenv default to null } } }
<span style="font-family: 微软雅黑, Microsoft YaHei;">Dotenv实例化Loader的时候把Loader对象的$immutable属性设置成了false,Loader设置变量的时候如果通过getEnvironmentVariable方法读取到了变量值,那么就会跳过该环境变量的设置。所以Dotenv默认情况下不会覆盖已经存在的环境变量,这个很关键,比如说在docker的容器编排文件里,我们会给PHP应用容器设置关于Mysql容器的两个环境变量</span><br>
environment: - "DB_PORT=3306" - "DB_HOST=database"
这样在容器里设置好环境变量后,即使env文件里的DB_HOST为homestead用env函数读取出来的也还是容器里之前设置的DB_HOST环境变量的值database(docker中容器链接默认使用服务名称,在编排文件中我把mysql容器的服务名称设置成了database, 所以php容器要通过database这个host来连接mysql容器)。因为用我们在持续集成中做自动化测试的时候通常都是在容器里进行测试,所以Dotenv不会覆盖已存在环境变量这个行为就相当重要这样我就可以只设置容器里环境变量的值完成测试而不用更改项目里的env文件,等到测试完成后直接去将项目部署到环境上就可以了。
如果检查环境变量不存在那么接着Dotenv就会把环境变量通过PHP内建函数putenv设置到环境中去,同时也会存储到$_ENV和$_SERVER这两个全局变量中。
在项目中读取env配置
在Laravel应用程序中可以使用env()函数去读取环境变量的值,比如获取数据库的HOST:
env('DB_HOST`, 'localhost');
传递给 env 函数的第二个值是「默认值」。如果给定的键不存在环境变量,则会使用该值。
我们来看看env函数的源码:
function env($key, $default = null) { $value = getenv($key); if ($value === false) { return value($default); } switch (strtolower($value)) { case 'true': case '(true)': return true; case 'false': case '(false)': return false; case 'empty': case '(empty)': return ''; case 'null': case '(null)': return; } if (strlen($value) > 1 && Str::startsWith($value, '"') && Str::endsWith($value, '"')) { return substr($value, 1, -1); } return $value; }
它直接通过PHP内建函数getenv读取环境变量。
我们看到了在加载配置和读取配置的时候,使用了putenv和getenv两个函数。putenv设置的环境变量只在请求期间存活,请求结束后会恢复环境之前的设置。因为如果php.ini中的variables_order配置项成了 GPCS不包含E的话,那么php程序中是无法通过$_ENV读取环境变量的,所以使用putenv动态地设置环境变量让开发人员不用去关注服务器上的配置。而且在服务器上给运行用户配置的环境变量会共享给用户启动的所有进程,这就不能很好的保护比如DB_PASSWORD、API_KEY这种私密的环境变量,所以这种配置用putenv设置能更好的保护这些配置信息,getenv方法能获取到系统的环境变量和putenv动态设置的环境变量。
以上是Laravel框架下ENV的加载和读取的介绍的详细内容。更多信息请关注PHP中文网其他相关文章!

Laravel在后端开发中的核心功能包括路由系统、EloquentORM、迁移功能、缓存系统和队列系统。1.路由系统简化了URL映射,提高了代码组织和维护性。2.EloquentORM提供了面向对象的数据操作,提升了开发效率。3.迁移功能通过版本控制管理数据库结构,确保一致性。4.缓存系统减少数据库查询,提升响应速度。5.队列系统有效处理大规模数据,避免阻塞用户请求,提升整体性能。

Laravel在后端开发中表现强大,通过EloquentORM简化数据库操作,控制器和服务类处理业务逻辑,并提供队列、事件等功能。1)EloquentORM通过模型映射数据库表,简化查询。2)业务逻辑在控制器和服务类中处理,提高模块化和可维护性。3)其他功能如队列系统帮助处理复杂需求。

选择Laravel开发项目是因为其灵活性和强大功能适应不同规模和复杂度的需求。Laravel提供路由系统、EloquentORM、Artisan命令行等功能,支持从简单博客到复杂企业级系统的开发。

Laravel和Python在开发环境和生态系统上的对比如下:1.Laravel的开发环境简单,仅需PHP和Composer,提供了丰富的扩展包如LaravelForge,但扩展包维护可能不及时。2.Python的开发环境也简单,仅需Python和pip,生态系统庞大,涵盖多个领域,但版本和依赖管理可能复杂。

Laravel是如何在后端逻辑中发挥作用的?它通过路由系统、EloquentORM、认证与授权、事件与监听器以及性能优化来简化和增强后端开发。1.路由系统允许定义URL结构和请求处理逻辑。2.EloquentORM简化数据库交互。3.认证与授权系统便于用户管理。4.事件与监听器实现松耦合代码结构。5.性能优化通过缓存和队列提高应用效率。

Laravel受欢迎的原因包括其简化开发过程、提供愉快的开发环境和丰富的功能。1)它吸收了RubyonRails的设计理念,结合PHP的灵活性。2)提供了如EloquentORM、Blade模板引擎等工具,提高开发效率。3)其MVC架构和依赖注入机制使代码更加模块化和可测试。4)提供了强大的调试工具和性能优化方法,如缓存系统和最佳实践。

Django和Laravel都是全栈框架,Django适合Python开发者和复杂业务逻辑,Laravel适合PHP开发者和优雅语法。1.Django基于Python,遵循“电池齐全”哲学,适合快速开发和高并发。2.Laravel基于PHP,强调开发者体验,适合小型到中型项目。

PHP和Laravel不是直接可比的,因为Laravel是基于PHP的框架。1.PHP适合小型项目或快速原型开发,因其简单直接。2.Laravel适合大型项目或高效开发,因其提供丰富功能和工具,但学习曲线较陡,性能可能不如纯PHP。


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

Dreamweaver Mac版
视觉化网页开发工具

EditPlus 中文破解版
体积小,语法高亮,不支持代码提示功能

SublimeText3 Linux新版
SublimeText3 Linux最新版

mPDF
mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

MinGW - 适用于 Windows 的极简 GNU
这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。