如何控制从 symfony1.4 任务中的 database.yml 选择哪个连接

How to control which connection is selected from the database.yml in a symfony1.4 task

(请参阅下面我的编辑以获得更好的问题) 如何控制 selected 的连接(来自 [=49= 中的正确环境部分) ]) 在 symfony1.4 任务中仅使用通用 Doctrine_Query::create() 来创建查询?

我使用的 database.yml 看起来像这样:

prod:
  doctrine:
    class: sfDoctrineDatabase
    param:
      dsn: mysql://some:pass@domain:port/database

  log:
    class: sfDoctrineDatabase
    param:
      dsn: mysql://some:pass@domain:port/database
  auth:
    class: sfDoctrineDatabase
    param:
      dsn: mysql://some:pass@domain:port/database

dev:
  doctrine:
    class: sfDoctrineDatabase
    param:
      dsn: mysql://some:otherpass@domain:port/database

  log:
    class: sfDoctrineDatabase
    param:
      dsn: mysql://some:otherpass@domain:port/database

  auth:
    class: sfDoctrineDatabase
    param:
      dsn: mysql://some:otherpass@domain:port/database

而且我希望能够控制在调用类似以下内容时使用这些数据库定义中的哪一个:

$query = Doctrine_Query::create()
        ->select('*')
        ->from('Products p')
        ->where('p.id = ?', $productID)
        ->limit(1);

$OfpFlPr = $query->execute()->getFirst();

目前我无法像这样设置连接$query = Doctrine_Query::create($conn);

如有任何帮助,我们将不胜感激!


编辑:

我在使用 Doctrine_Query::create() 的软件中有很多更深入的代码(没有连接参数)。似乎 select 正确的环境和通过网络请求的连接。但我不知道它是如何做到这一点的,所以我可以让我的 CLI 命令 以相同的方式工作(它们 select 正确的连接和环境片刻)。这就是为什么我需要知道如何控制 'automaticly' 使用哪个连接(默认情况下 select)。

问题:

所以我想最后我的问题是:

当代码作为 symfony CLI 命令执行时,我如何控制在使用 Doctrine_Query::create() 的较低级别代码中默认 selected 哪个连接?

$query = Doctrine_Query::create($doctrineManager->getConnection('doctrine'))
    ->select('*')
    ->from('Products p')
    ->where('p.id = ?', $productID)
    ->limit(1);

应该可以。根据您 select 您的 Product 来自哪里,参数可能是 'doctrine'、'log' 或 'auth'。

你能详细说明你为什么 "not able to set the connection" 这样吗?

编辑:

所以如果我做对了,你喜欢在 cli 命令中指定环境,使用 database.yml 中右侧部分的 dsn 连接字符串。您可以为您的 cli 命令使用 env 选项来执行此操作。您可能需要添加类似

的内容
$this->addOption('env', null, sfCommandOption::PARAMETER_OPTIONAL, 'Specify environment', 'prod'); 

到任务配置。

默认情况下,使用此代码生成任务:

$databaseManager = new sfDatabaseManager($this->configuration);
$connection = $databaseManager->getDatabase($options['connection'])->getConnection();

这只会初始化一个连接,不会初始化上下文。相反,将其替换为:

sfContext::createInstance(new frontendConfiguration($options['env'], true));

这将创建上下文,使用任务的 application 选项。您可能想为其设置默认值,将任务的 configure() 方法更改为:

    $this->addOptions(array(
        new sfCommandOption('application', null, sfCommandOption::PARAMETER_REQUIRED, 'The application name', 'frontend'),
        // ...
    ));

注意我添加了 frontend 来初始化前端应用程序。您还可以调整 env 选项的默认值。

我实际问题的原因

在使用干净创建的任务进行深入调试后,我终于找到了罪魁祸首。 Symfony 1.4 似乎 运行 configure 任务目录中每个任务的方法,然后才真正 运行 执行预期的任务。

不幸的是,一些不知情的恶作剧者(前同事*)在这些方法之一中包含了一些硬编码的上下文初始化,如下所示:

// inside a task
protected function configure() {
    // context was initialized
    $configuration    = ProjectConfiguration::getApplicationConfiguration('app_name', 'prod', true);
    $context          = sfContext::createInstance($configuration);

    // so the following was available in the configure method
    $save_path = sfConfig::get('sf_app_config_dir');

    // rest of configure method implementation 
    // ...
}

除了生产环境(幸运的是),这搞砸了所有其他环境中所有 cronjobs 的数据库设置。

我设法通过做这样的事情来解决它:

protected function configure() {
    $configuration    = ProjectConfiguration::getApplicationConfiguration('app_name', 'prod', true);
    // removed the context creation

    $configuration->activate(); // this makes the sfConfig::get() work
    $save_path = sfConfig::get('sf_app_config_dir');

    // rest of configure method implementation 
    // ...
}

回答我的问题

我还发现,在控制 Doctrine_Query::create() 使用哪个数据库连接时,您可以通过在更高级别的函数上使用类似这样的东西来进行一些控制:

// for making sure the 'auth' database settings are used as a default
Doctrine_Manager::getInstance()->setCurrentConnection('auth');

但是,这对 'environment section' 用于 select 数据库的权利 configuration/dsn 没有任何影响。这是通过做这样的事情来完成的:

// somewhere in the execute method
$env              = 'dev'; // the environment section name; 
$configuration    = ProjectConfiguration::getApplicationConfiguration('app_name', $env, true);
$context          = sfContext::createInstance($configuration);

正如 and 的答案中正确暗示的那样。使用任务 'option' 使其支持多种环境,正如他们建议的那样。

*:我的前同事,因为这个问题的不太可能和反直觉的性质,我很难生气 ;)