【问题标题】:Environment driven database settings in Laravel?Laravel 中的环境驱动数据库设置?
【发布时间】:2012-12-01 08:50:51
【问题描述】:

我正在迁移 Laravel 框架,但我在数据库设置方面遇到了问题,

具体来说,我已经设置了我的环境,它们在 application.php 配置文件中运行良好,但是 database.php 配置文件似乎没有效果。

即使我的环境文件夹中有一个 database.php 配置文件,它也永远不会加载,我将一堆无效字符(键盘混搭)放入文件中以使 php 抛出错误,但它从未被命中。

Laravel 不支持基于环境的数据库设置吗?还是我做错了?

【问题讨论】:

  • 这是我第一次听说基于环境的数据库设置。你如何设置这些?以及使用它有什么好处?几周前我也开始学习 laravel,我也玩过 fluent 和 eloquent 之类的数据库类,但从未遇到过。
  • 它基于环境,docs,它应该适用于任何配置文件,不确定是什么问题。
  • 你确定正在加载config文件夹中的database.php文件吗?您是否尝试过从那里抛出错误?
  • 另外,您是否确保正在加载环境文件夹中的其他配置?也许 Laravel 只是不知道你是在测试、开发还是生产?

标签: php database environment laravel


【解决方案1】:

您绝对可以按环境设置数据库设置(以及任何其他配置设置)。

对于 Laravel 3(对于 Laravel 4 和 Laravel 5,请参见下文):

首先 - 您需要在 paths.php 中定义 $environments 并将其设置为如下内容:

$environments = array(
  'development' => array('*.dev'),
  'production' => array('*.com'),
);

Laravel 会自动寻找这个变量,如果设置了,就会使用相关的配置。

通常您有一个config 文件夹,其中包含database.phpauth.php 等设置

现在只需为您计划使用的每个 Laravel_Env 创建一个新文件夹(例如 Development)。您最终会得到这样的文件夹结构;

/application
  /config
    /development
      database.php
    /production
      database.php
    application.php
    config.php
    database.php
    ...
    user_agents.php

您会注意到我只在每个子文件夹中包含了database.php。 Laravel 将始终首先加载默认配置设置,然后使用环境设置中的任何自定义配置覆盖它们。

最后,在你的开发/数据库文件中,你会有这样的东西;

<?php
 return array(
'default' => 'mysql'
 );

附言我刚刚在 Laravel 的当前 3.2.12 版本上测试了它——它确实有效。

额外提示:您还可以为 Artisan 自动设置环境,因此您不必在每个命令行中手动包含环境!为此:

  1. 您需要知道运行 Artisan 的“主机名”。要找出答案 - 临时编辑根文件夹中的 artisan.php,并将 var_dump(gethostname()); 添加到第 2 行(即高于一切)。

  2. 从命令行运行php artisan。您将获得一个带有您的主机名的字符串转储。就我而言,它是“TSE-Win7”;

  3. 删除对artisan.php文件的更改

  4. 将您的主机名(即“TSE-Win7”)添加到环境中。

你应该得到这样的结果:

$environments = array(
  'development' => array('*.dev', 'TSE-Win7'),
  'production' => array('*.com'),
);

Artisan 现在将使用您的开发环境运行。如果您部署到实时服务器 - 重新运行这些步骤以获取服务器的主机名(),您可以为服务器配置特定的工匠配置!

对于 Laravel 4:

默认环境始终为production。但在您的 start.php 文件中,您可以定义其他环境。

 $env = $app->detectEnvironment(array(
   'local' => array('your-machine-name'),
));

在 Linux 和 Mac 上,您可以通过在终端中键入 hostname 来确定您的 hostname - 它会输出您的计算机名称。在 Windows 上,将 dd(gethostname()); 放在您的 routes.php 文件的开头 - 并运行该网站一次 - 它会显示您计算机的当前主机名。

要在您的应用程序中将当前环境作为变量获取 - 请在此处阅读此 SO 答案。 Laravel 4: how can I get the environment value?

对于 Laravel 5:

在您的根目录中有一个名为.env 的配置文件。 Watch this laracast,配置解释完整。

【讨论】:

  • 感谢 Laravel IRC 的“JoelLarson”和“Kindari”,他们帮助开发了工匠解决方案。
  • 感谢工匠小费!我喜欢使用 artisan 来执行 cronjob 任务,这让它变得更加容易!
  • 我遇到的问题是我正在运行 artisan,但我不知道它加载了它自己的配置,所以你的 artisan 提示是修复 :)
  • 我在端口 8888 上使用 MAMP,并且 *.dev 未被识别 - 使用你的工匠技巧解决了问题 - tx!
  • 我能够将本地环境设置为默认传递 $app->detectEnvironment(array( 'production' => array('my-production-hostname'), 'local' => array( '*') ));
【解决方案2】:

如果你使用的是 artisan(laravel 的命令行)你需要添加的每个命令

artisan bla bla bla --env=Development 

artisan bla bla bla --env=Production

【讨论】:

  • 你是对的 - 但实际上有一种方法可以自动化该过程。我已经编辑了答案以显示所需的步骤。
【解决方案3】:

这就是我如何根据自己的需要进行设置的。

我个人需要 4 种不同的配置:

  1. localhost (Mac OSX) - /Library/WebServer/Documents/www/my-domain.com/development/
  2. dev.my-domain.com (VPS) - /var/www/my-domain.com/development/
  3. test.my-domain.com (VPS) - /var/www/my-domain.com/test/
  4. my-domain.com (VPS) - /var/www/my-domain.com/web/

由于我所有的 4 个环境都有不同的目录结构,我可以使用 php 的魔术常量 __DIR__ 来获取应用程序目录,然后使用 strpos() 函数来做简单的检查并返回相应的环境。它还会处理 Artisan 环境,无需手动输入环境或添加任何机器名称。

里面

bootstrap/start.php

添加回调函数

$env = $app->detectEnvironment(function(){

  $haystack = __DIR__; // Catch the directory path

  // Set the booleans (remove the first '/', else strpos() will return 0)
  $isLocal       = strpos($haystack, 'Library/WebServer/Documents/www/my-domain.com/development/');
  $isDevelopment = strpos($haystack, 'var/www/my-domain.com/development/');
  $isTest        = strpos($haystack, 'var/www/my-domain.com/test/');
  $isProduction  = strpos($haystack, 'var/www/my-domain.com/web/');

  // Set the environments
  if ($isLocal)       $environment = "local";
  if ($isDevelopment) $environment = "development";
  if ($isTest)        $environment = "test";
  if ($isProduction)  $environment = "production";

  // Return the appropriate environment
  return $environment
});

另一种选择

我们还可以一次将所有值设置并抓取到一个数组中,然后运行一个 foreach 循环。

提示:因为我们使用 strpos() 函数,它会根据 $haystack 检查给定值第一次出现的位置,并返回位置编号。我们实际上不必提供整个路径,我们可以简单地从每条路径中添加一个独特的值来完成工作。

// Check the boolean, if true set to given value, else set NULL
$environments[] = strpos($haystack, "Library") ? 'local'      : NULL;
$environments[] = strpos($haystack, "develop") ? 'development': NULL;
$environments[] = strpos($haystack, "test")    ? 'test'       : NULL;
$environments[] = strpos($haystack, "web")     ? 'production' : NULL;

// Loop through each, if not null then we have our environment
foreach ($environments as $environment) {
     if(!is_null($environment))
     return $environment;
}

无论我们在一台机器还是多台机器上工作,通过相同路径进入不同环境的可能性非常小。

至少我是这么认为的。 :)

【讨论】:

    【解决方案4】:

    How to setup environment specific configuration 现在在 Laravel 官方文档中。我建议使用他们的方法而不是接受的答案:

    根据不同的配置值设置不同的配置值通常很有帮助 应用程序运行的环境。例如,您可以 希望在本地开发机器上使用不同的缓存驱动程序 比在生产服务器上。使用很容易做到这一点 基于环境的配置。

    只需在配置目录中创建一个与您的匹配的文件夹 环境名称,例如本地。接下来,创建配置文件 您希望覆盖并指定该环境的选项。为了 例如,要覆盖本地环境的缓存驱动程序,您 将在 app/config/local 中创建一个 cache.php 文件,其中包含以下内容 内容:

    <?php    
    return array(    
        'driver' => 'file',    
    );
    

    注意:不要使用“测试”作为环境名称。这是保留的 用于单元测试。请注意,您不必指定每个选项 这是在基本配置文件中,但只有你想要的选项 覆盖。环境配置文件将“级联” 基础文件。

    接下来,我们需要指示框架如何确定哪个 它运行的环境。默认环境总是 生产。但是,您可以在 bootstrap/start.php 文件位于安装的根目录。在这个 文件你会发现一个 $app->detectEnvironment 调用。数组通过 这个方法是用来判断当前环境的。你可以 根据需要将其他环境和机器名称添加到数组中。

    <?php
    
    $env = $app->detectEnvironment(array(    
        'local' => array('your-machine-name'),    
    ));
    

    在本例中,'local' 是环境的名称,并且 'your-machine-name' 是您的服务器的主机名。在 Linux 和 Mac 上, 您可以使用主机名终端命令确定您的主机名。

    如果您需要更灵活的环境检测,您可以通过 关闭 detectEnvironment 方法,允许您实现 随心所欲的环境检测:

    $env = $app->detectEnvironment(function()
    { 
        $domain = explode('.', $_SERVER['HTTP_HOST']);
        switch($domain[0])
        {
            case 'localhost':
            case 'localhost:8080':                
            case 'dev':
                return 'development';
                break;
            case 'mysite':
            default:
                return 'production';
                break;
        }
    });
    

    您可以通过环境访问当前的应用环境 方法:

    访问当前的应用程序环境

    $environment = App::environment();
    

    您也可以将参数传递给环境方法以检查是否 环境匹配给定值:

    if (App::environment('local'))
    {
        // The environment is local
    }
    
    if (App::environment('local', 'staging'))
    {
        // The environment is either local OR staging...
    }
    

    【讨论】:

    • Justin:我在 start.php 中添加了新环境。 $env = $app->detectEnvironment(array('local' => array('localhost'),));在那之后,我确实喜欢下面。 $envname = App::environment();回声 $envname;它返回生产。请指教。如何获取本地环境名称?提前致谢。 :)
    • 如果你将一个数组传递给$app-&gt;detectEnvironment(),它期望你的机器名作为第二个值。您的机器名称肯定不是您使用的localhost。搜索谷歌如何找到你的真实机器名称或传递一个函数而不是一个数组来获取基于 URL 的环境......我将添加一个例子。
    【解决方案5】:

    Laravel 5

    使用the Laravel docs here 中详述的DotEnv 方法。

    Laravel 4

    我们正在使用 Laracasts lesson 中推荐的方法 Jeffrey Way。

    • 创建config 目录for each environment

      /app
          /config
              /local
                  database.php
              /production
                  database.php
      
    • 在生产服务器上设置环境变量。谷歌为您的生产平台上的最佳方法。例如,以下是针对UbuntuDreamhostHeroku 的好建议。我们在/etc/environment 中添加了一行:

      ENV=production
      
    • 将此闭包添加到/bootstrap/start.php。使用此设置,任何缺少ENV 环境变量的服务器都将默认为local 环境配置。

      $env = $app->detectEnvironment(
          function () {
              return getenv('ENV') ? : 'local';
          }
      );
      

    【讨论】:

      【解决方案6】:

      我今天一直在努力解决这个问题,努力找出如何最好地为数据库进行环境设置。最后,在尝试了几种方法之后,我完全同意@troy-harvey 的观点,即 Jeffrey Way 的建议是最好的(至少对我来说)。我要补充的一件事,它让我今天如此困扰的是(如果我错了请纠正我)你需要访问你试图覆盖的设置您的环境设置文件通过其相应的数组键。我开始返回一个简单的数组:

      return [
          'database' => '<db_name>',
          'username' => '<db_user>',
          'password' => '<db_pass>',
      ]; 
      

      app/config/staging/database.php 内。这没有任何效果,并且在头疼之后意识到您需要访问 app/config/database.php 中显示的数组,如下所示:

      <?php
      
      return [
      'connections' => [
          'mysql' => [
              'database' => '<db_name>',
              'username' => '<db_user>',
              'password' => '<db_pass>'
          ]
        ]
      ];
      

      至少这就是我最终设法获得我的设置的方式。

      在这里添加它以防其他人正在努力解决这个问题。当我意识到我犯了一个多么明显的错误时,我明白了。

      2014 年 7 月 1 日编辑

      对此的补充说明是,从 4.1 开始,Laravel 附带了一个 append_config() 辅助函数,用于将环境配置附加到主配置数组。

      对于上面给出的示例,这看起来像这样:

      <?php
      
      return append_config([
           'connections' => [
              'mysql' => [
                   'database' => '<db_name>',
                   'username' => '<db_user>',
                   'password' => '<db_pass>'
              ]
            ]
         ]);
      

      【讨论】:

      • 您也可以简单地将 database.php 文件(位于 app/config/ 中)直接复制到您的环境文件夹中(例如在 app/config/local 目录中),然后使用您的本地数据库设置。
      【解决方案7】:

      在 Laravel 3 中检测环境:

      Request:env()
      

      这将返回在 paths.php 文件中找到的环境数组中标识的任何内容。

      正如之前在 Laravel 4 中提到的,现在是:

      App:: environment()
      

      【讨论】:

        【解决方案8】:

        我的做法!

        $env = $app->detectEnvironment( function() {
            if ( file_exists('../.env.local.php') ) {
                return 'local';
            }
            if ( file_exists('../.env.beta.php') ) {
                return 'beta';
            }
            return 'production';
        } );
        

        【讨论】:

          【解决方案9】:

          如果您尝试在 Windows 环境中使用 Laravel,请检查您的 Laravel 项目顶级文件夹中的 .env 文件中的设置 - 这些将覆盖您在 config/database.php 中的任何数据库设置

          【讨论】:

            【解决方案10】:

            如果您在 Laravel 4 here is a gist 上,它将逐步引导您完成整个过程。感谢@“The Shift Exchange”的回答指导我创建它。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2012-12-27
              • 1970-01-01
              • 2015-06-15
              • 2015-04-19
              • 1970-01-01
              • 2015-05-02
              相关资源
              最近更新 更多