【问题标题】:problem with zend module specific configurationzend 模块特定配置的问题
【发布时间】:2011-03-04 07:25:29
【问题描述】:

我正在使用 zend 框架构建 REST Web 服务,并且我正在使用模块来分隔我的 api 版本。

现在,我想为我的每个模块(v1 和 v2)创建一个单独的配置文件,主要用于指定单独的数据库连接。

我有一个这样的目录结构:

- application
      - modules
            - v1
                  - controllers
                  - models
                  - views
                  - configs
                    - module.ini         
            - v2
                  - controllers
                  - models
                  - views  
                  - configs
                    - module.ini
      - configs
            - application.xml   
- library

我已经在 application/configs 中的“application.ini”中提到了数据库连接。我阅读了 here 关于模块特定的配置并尝试了它。

我从 application.ini 中删除了这些数据库参数并将其放入 module.ini 中:

[production]
resources.db.adapter = PDO_MYSQL
resources.db.params.host = 127.0.0.1
resources.db.params.username = myuser   
resources.db.params.password = mypwd
resources.db.params.dbname = my_db
resources.db.params.profiler.enabled = "true"
resources.db.params.profiler.class = "Zend_Db_Profiler_Firebug"

.....

但是当我访问模块控制器中的数据库时,我收到一条错误消息“未找到适配器...”。请帮忙...

【问题讨论】:

  • 需要更多信息 - 您在哪一行得到错误?这是一个 PHP 致命错误吗?
  • 我认为这只是一个正常的错误消息。但错误后执行停止。
  • 您能否将其添加到 /public/.htaccess 文件中:SetEnv APPLICATION_ENV "development" 然后告诉我们错误详情。
  • 你不能只使用特定于模块的引导程序吗?
  • @Perfection:我收到诸如“未找到适配器...”之类的错误

标签: php zend-framework


【解决方案1】:

在引导程序中,您可以设置数据库连接:

protected function _initDb () {
    $config['my_db1'] = new Zend_Config_Ini(APPLICATION_PATH . '/configs/my_db1.ini');
    $config['my_db2'] = new Zend_Config_Ini(APPLICATION_PATH . '/configs/my_db2.ini');

    $my_db1 = new Plugin_Replication($config['my_db1']->toArray());
    $my_db1->query("SET CHARACTER SET utf8;");

    $my_db2 = new Plugin_Replication($config['my_db2']->toArray());
    $my_db2->query("SET CHARACTER SET utf8;");

    Zend_Db_Table::setDefaultAdapter($dmy_db1);
    Zend_Registry::set('my_db1', $my_db1);
    Zend_Registry::set('my_db2', $my_db2);
}

在我的例子中,每个连接都在一个单独的 .ini 文件中指定。我发现这非常直观地组织起来。数据库 ini 文件不需要 resources.db.whatever 名称。我的是这样的:

[Master]
host = "xxx"
username = "xxx"
password = "xxx"
dbname = "xxx"
charset = utf8

[Slaves]
first.host = "xxx"
first.username = "xxx"
first.password = "xxx"
first.dbname = "xxx"
first.charset = utf8

second.host = "xxx"
second.username = "xxx"
second.password = "xxx"
second.dbname = "xxx"
second.charset = utf8

一旦您像这样设置了多个数据库,在创建模型时(在您希望的任何模块中),您可以告知 ZF 您想要使用的数据库:

protected function _setupDatabaseAdapter() {
    $this->_db = Zend_Registry::get('my_db1');
}

这将是您的默认适配器。如果您需要在同一个查询中使用两个数据库,请使用以下命令启动模型的功能:

public function myAwesomeSqlQuery () {
    $db1 = $this->getAdapter()->getConfig(); //default adapter
    $db2 = Zend_Registry::get('my_db2')->getConfig(); //additional adapter

现在,您可以通过这种方式使用这两个数据库编写查询:

$sql = $this
    ->select()
    ->setIntegrityCheck(false)
    ->from(array('col1' => $db1['dbname'].'.some_column'))
    ->join(array('col2' => $db2['dbname'].'.some_other_column')),'col1.id = col2.id')
;

正如我在评论中所建议的,您还可以使用特定于模块的引导程序。结构如下:

/application/
  -- /modules/
    -- /v1/
        -- /controllers/
        -- /views/
        -- /Bootstrap.php
    -- /v2/
        -- /controllers/
        -- /views/
        -- /Bootstrap.php

特定于模块的引导程序的构造与任何其他引导程序非常相似,但它们会影响相关模块。类名通常以模块名作为前缀,例如:

<?php
class V1_Bootstrap extends Zend_Application_Bootstrap_Bootstrap {
    ...
}

我通常尽量不使用特定于模块的引导程序,因为它们都是随每个请求启动的(Zend Framework 2 应该纠正这个问题),运行当前模块不需要的功能。无论如何,我在我的一个模块中找到了一个特定于模块的引导程序,其中包含如下内容:

class MyModule_Bootstrap extends Zend_Application_Bootstrap_Bootstrap {
    protected function _initLoggers () {
        $my_db1 = Zend_Registry::get('my_db1');
        $my_db2 = Zend_Registry::get('my_db2');
        $my_db1->setProfiler(new Zend_Db_Profiler_Firebug())->getProfiler()->setEnabled(true);
        $my_db2->setProfiler(new Zend_Db_Profiler_Firebug())->getProfiler()->setEnabled(true);

        $auth = Zend_Auth::getInstance();
        $columnMapping = array('priority' => 'priority' , 'message' => 'message' , 'timestamp' => 'timestamp' , 'username' => 'username');
        $logger = new Zend_Log(new Zend_Log_Writer_Db($my_db1, 'logs', $columnMapping));
        print_r($auth->getIdentity());
        if ($auth->hasIdentity())
            $logger->setEventItem('username', $auth->getIdentity()->username);
        Zend_Registry::set('logger', $logger);
    }

差不多就是这样。希望对你有帮助。

【讨论】:

  • Mingos,我想试试你的解决方案,但我对模块的模型部分感到困惑......你能发布与模型相关的代码以及如何从模型或控制器查询
  • 答案尽在其中。您具体遇到了什么问题?
  • 我已经在我的应用程序引导程序中编写了 initDb() 方法,并且还添加了 2 个单独的数据库配置文件,如上所述。但我不明白在哪里编写 _setupDatabaseAdapter() 方法。是否在 modules/my_module/models/bootstrap 文件中
  • 不不不,它进入你的模型:)。它告诉模型默认使用哪个数据库:)
  • 是的:)。抱歉,我只是在使用更复杂的设置,有一个主服务器和两个从服务器。复制用于将主服务器上的所有更改复制到从服务器。你可以摆脱这些线条。我根本不应该复制它们。
【解决方案2】:

您在问题中提到的解决方案 (My_App) 不需要针对特定​​模块的数据库连接或任何其他特定于模块的配置(路由除外)进行任何额外配置。您需要做的就是在application.ini 中声明一个MultiDb 资源 为db1。然后,您可以在所请求模块的相应 module.ini 中将任何特定于模块的数据库资源声明为 db2、db3、db4... 等...您不需要任何额外的配置。我在我的 github 的下载文件中放置了一个示例。不要不尊重上面“mingos”的回应,但My_App中不需要任何额外的代码。

这是从下载 (application.ini) 中获取的确切内容:

...if this resource is declared here, then it
will be available to all modules. If different
db resources need to be used for different
modules then MultiDB resource can be
initiated. Example: A general db resource can be
defined here and a module specific db can be
declared in its corresponding module.ini.
The db resource declared in the module will not
be available to other modules but the db resource
in this application.ini will be available to all
modules...

然后它在下载中声明一个单独的 db 资源作为示例。只需将其更改为多数据库资源即可。在 application.ini 中声明应用程序范围所需的 db 资源,并在其各自的 module.ini 文件中声明任何特定模块所需的任何其他 db 资源。这很简单。这就是你需要做的。一旦你理解了 My_App 背后的逻辑,你就会发现它非常强大。

【讨论】:

  • 感谢 osebboy 的友好回答。你太棒了。你能提一下我需要在 application.ini 中写下声明 MultiDb 资源的那一行吗?
  • #resources.multidb.db1.adapter = "pdo_mysql" #resources.multidb.db1.host = "localhost" #resources.multidb.db1.username = "webuser" #resources.multidb.db1 .password = "XXXX" #resources.multidb.db1.dbname = "db1" 以上是multiDb资源的初始声明。您可以在 application.ini 中声明。由于它是在 application.ini 中声明的,因此它可用于所有模块。现在,如果您在特定模块中需要任何额外的 Db 资源,那么您可以在其各自的 module.ini 中将该资源声明​​为 db2、db3...
  • 这样你就可以拥有一个应用程序范围的数据库资源和模块特定的数据库资源。不需要代码。请记住,My_App 创建了完全隔离的模块。我建议你尝试理解 My_App 背后的逻辑。
  • 谢谢,成功了。我在 module.ini 文件中为我的每个模块(包括默认模块)指定了单独的数据库配置。效果很棒。
  • 太棒了...您还可以声明模块特定的布局、控制器插件和其他资源。如果您可以更深入地了解主题,那么与它有很多关系。
【解决方案3】:

osebboy 的解决方案未配置为具有 .ini 以外的配置文件。你有application.xml。根据 osebboy 的解决方案,初始设置似乎不正确。

我建议你从他的 github 下载源代码并设置它。另请阅读他的博客文章。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-09
    • 2011-01-27
    • 1970-01-01
    • 1970-01-01
    • 2020-07-30
    • 2021-02-05
    相关资源
    最近更新 更多