Laravel 5.1 没有使用正确的 .env 值

Posted

技术标签:

【中文标题】Laravel 5.1 没有使用正确的 .env 值【英文标题】:Laravel 5.1 not using correct .env values 【发布时间】:2017-01-30 06:26:24 【问题描述】:

我使用的是 Laravel 5.1.44,即使我有一个具有不同值的 .env.testing 文件设置,以及返回 'testing'App::environment(),Laravel 似乎仍然只使用来自主.env 文件。

还有什么我应该仔细检查以确保我没有搞砸或忘记设置什么吗?

【问题讨论】:

你可能需要在phpunit.xml中注册 好像已经设置好了:php <env name="APP_ENV" value="testing"/> <env name="CACHE_DRIVER" value="array"/> <env name="SESSION_DRIVER" value="array"/> <env name="QUEUE_DRIVER" value="sync"/> 我很确定您只能拥有一个 .env 文件。你可以使用config目录下的配置文件为每个环境定义多个配置,然后你可以通过.env或PHPUnit文件设置env 看看laracasts.com/discuss/channels/testing/… 是的,我也看到了,在那个例子中,他们使用.env.testing 文件为他们的testing 环境定义值。我的问题是,当我的环境是testing 时,它不会从.env.testing 读取值,而只是从.env 读取值。根据 Laravel 使用的 'dotenv' 库中的文档,它应该像为该环境创建另一个点文件一样简单,文件名格式为 .env.environmentName 【参考方案1】:

在 Laravel 5.2.13 之前,无法使用环境特定的 .env 文件(例如 .env.testing)。即使那样,它也只有在您不使用配置缓存时才有效。

最简单的选择是将所有测试特定的环境变量添加到phpunit.xml 文件中。正如你所提到的,你已经有了一些,添加任何你需要的额外的应该没有问题。

如果你真的想要 Laravel 5.1 中特定于环境的 .env 文件功能,你可以尝试以下方法。请注意,这是未经测试的,只是基于查看源代码的假设。

.env 文件加载到名为 DetectEnvironment 的引导类中。这个想法是您创建自己的引导类来修改DetectEnvironment 将加载的.env 文件的文件名,然后更新您的Kernel 文件,以便调用新的引导类,并在 DetectEnvironment 引导程序。

所以,首先,创建一个新的引导程序类(例如app\Bootstrap\CustomEnvironment.php):

<?php
namespace App\Bootstrap;

use Illuminate\Contracts\Foundation\Application;

class CustomEnvironment

    /**
     * Bootstrap the given application.
     *
     * @param  \Illuminate\Contracts\Foundation\Application  $app
     * @return void
     */
    public function bootstrap(Application $app)
    
        // APP_ENV must already be set.
        // We must know which environment file to look for.
        if (! env('APP_ENV')) 
            return;
        

        // Build the file name to look for (e.g. .env.testing)
        $file = $app->environmentFile().'.'.env('APP_ENV');

        // If the file exists, set the App to load from that file.
        // The actual loading will take place in DetectEnvironment
        if (file_exists($app->environmentPath().'/'.$file)) 
            $app->loadEnvironmentFrom($file);
        
    

现在您有一个引导类来更新要加载的.env 文件,您需要将它添加到您的Kernel|s 以确保在DetectEnvironment 引导类之前调用​​它。

将以下属性添加到您的 app/Console/Kernel.php 文件中:

/**
 * The bootstrap classes for the application.
 *
 * @var array
 */
protected $bootstrappers = [
    'App\Bootstrap\CustomEnvironment',
    'Illuminate\Foundation\Bootstrap\DetectEnvironment',
    'Illuminate\Foundation\Bootstrap\LoadConfiguration',
    'Illuminate\Foundation\Bootstrap\ConfigureLogging',
    'Illuminate\Foundation\Bootstrap\HandleExceptions',
    'Illuminate\Foundation\Bootstrap\RegisterFacades',
    'Illuminate\Foundation\Bootstrap\SetRequestForConsole',
    'Illuminate\Foundation\Bootstrap\RegisterProviders',
    'Illuminate\Foundation\Bootstrap\BootProviders',
];

将以下属性添加到您的 app/Http/Kernel.php 文件中:

/**
 * The bootstrap classes for the application.
 *
 * @var array
 */
protected $bootstrappers = [
    'App\Bootstrap\CustomEnvironment',
    'Illuminate\Foundation\Bootstrap\DetectEnvironment',
    'Illuminate\Foundation\Bootstrap\LoadConfiguration',
    'Illuminate\Foundation\Bootstrap\ConfigureLogging',
    'Illuminate\Foundation\Bootstrap\HandleExceptions',
    'Illuminate\Foundation\Bootstrap\RegisterFacades',
    'Illuminate\Foundation\Bootstrap\RegisterProviders',
    'Illuminate\Foundation\Bootstrap\BootProviders',
];

注意,它们乍一看可能很相似,但 ConsoleHttp 内核之间的引导程序不同(Console 有一个引导程序)。不要只复制上述内容之一并将其添加到两个文件中。

编辑

另一种更简单的方法是为 DetectEnvironment 引导程序设置一个 before 侦听器,并将文件设置为在事件闭包中加载。

因此,例如,在您的bootstrap\app.php 文件中,在return $app; 语句之前添加以下代码:

$app->beforeBootstrapping(
    'Illuminate\Foundation\Bootstrap\DetectEnvironment',
    function($app) 
        // APP_ENV must already be set.
        // We must know which environment file to look for.
        if (! env('APP_ENV')) 
            return;
        

        // Build the file name to look for (e.g. .env.testing)
        $file = $app->environmentFile().'.'.env('APP_ENV');

        // If the file exists, set the App to load from that file.
        // The actual loading will take place in DetectEnvironment
        if (file_exists($app->environmentPath().'/'.$file)) 
            $app->loadEnvironmentFrom($file);
        
    
);

使用beforeBootstrapping()方法,第二个参数中的闭包将在第一个参数中的引导程序被调用之前立即执行。现在您不必担心内核或额外的类或任何东西。

【讨论】:

我慢慢发现,过去一个小时里,5.1 只支持一个.env 我自己。很困惑,因为就我个人而言,Laravel 5.2 是我对框架的第一次介绍,但是对于一个新客户端,我决定使用最新的 LTS 版本,即 5.1。我确实最终让它以另一种方式工作,使用这里的方法(但对闭包代码进行了大量修改):developers.ph/laravel-framework/laravel-5/…,尽管你的方式可能更好。我现在只使用.env 文件。 @SteveFromAccounting 我用一个更简单的解决方案更新了我的答案。同样,未经测试,但应该基于源代码审查工作。

以上是关于Laravel 5.1 没有使用正确的 .env 值的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 5.1:Elastic Beanstalk 工作层设置队列

如何在 Laravel 5.1 中改变环境?

Laravel 5.1 在主机上上传

为啥 phpunit 没有得到 phpunit.xml 中指定的正确 APP_ENV?

Laravel Artisan CLI 没有设置正确的 URL

在 Laravel 5.1 配置文件中读取 Vhosts 中设置的环境变量