首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Zend Framework2模块在控制器之间共享变量onBootstrap

Zend Framework2模块在控制器之间共享变量onBootstrap
EN

Stack Overflow用户
提问于 2013-01-03 03:38:45
回答 1查看 12K关注 0票数 5

是否可以在Module.php中创建变量甚至共享对象(如DB适配器),以便在所有视图控制器中使用?(Zend Framework 2)

例如:

代码语言:javascript
复制
class Module 
{
    public function onBootstrap(MvcEvent $e)
    {

        $moduleConfig = $e->getServiceManager()->get('Config')
    }
}

在控制器中,以某种方式访问,使用:

代码语言:javascript
复制
$this->moduleConfig['db']

在上面,我知道这只是db适配器的配置数组,但它是如何工作的呢?

我看到可以在控制器操作中做到这一点:

代码语言:javascript
复制
$config = $this->getServiceLocator()->get('Config')
$dba = new DbAdapter($config['db']);

我不想在我需要配置的每个地方都这样做。我如何才能使它类似于:$this->config?所以它对所有动作都是可用的。更好的是,如何在整个模块中做到这一点?我知道我这样做是错的,但是在ZF1中,我们有Zend_Registry::get()来做这样简单的事情。我正在阅读文档和各种各样的tuts,但总是有一些假设,我只是迷路了。所以我真正想要的是: A)一个全局可访问的配置项,B)一个全局可访问的数据库适配器

我只想调用控制器中的$this->db或$this->config->项。这个是可能的吗?我知道我错过了一些非常简单的东西。

此外,我也尝试过使用$this->getServiceLocator()->get(‘Config’)在我的__construct中设置$this->配置;但我知道服务定位器在构造期间还不可用。我尝试通过在模块的onBootstrap中设置一个preDispatch来执行类似的操作,但似乎无法将这些项放入我的控制器中。

仅供参考,我的global.php中确实有这个(不,它没有停留在那里,只是举个例子):

代码语言:javascript
复制
'db' => array(
        'driver' => 'Pdo',
        'dsn'   => 'mysql:dbname=mydb;host=localhost;',
        'username' => 'root',
        'password' => '',
        'driver_options' => array(
            PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
        ),

    ),

我可以使用getServiceLocator()在任何操作中访问该项目和其他项目。我希望这些项作为我的控制器属性可用,如$this->config->item中所示。

感谢您的指导!谢谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-01-04 03:34:06

好吧..。多部分答案。

1.添加站点范围的配置变量。(以及如何在控制器中访问)

这很简单,当我看到它工作的时候。但这取决于下面的preDispatch。在您的应用程序根目录中,将一个文件放入config/autoload。取名为: things.config.local.php

在这个文件中,我们只返回一个带有配置项的数组。

代码语言:javascript
复制
<?php
return array(
    'things' => array(
        'avalue' => 'avalue1',
        'boolvalue' => true,
        ),

);

所以我想在我的控制器中访问它。假设您在控制器中创建了一个config属性,您可以这样访问它。(您可以在下面的preDispatch中设置该属性以使其正常工作)在我的系统中,我更喜欢这样检索该值:

代码语言:javascript
复制
$this->config['things']['boolvalue'];

但是,您可以在如下所示的操作中调用它:

代码语言:javascript
复制
$config = $this->getServiceLocator()->get('Config');
echo $config['things']['boolvalue'];

实际上,这很容易。不确定如何使用ini文件,但在我的例子中,不需要这样做,并且我的ini文件直接移到数组中并不是什么大问题。问题1为我解决了!

2.如何在控制器中获取preDispatch (因为__construct不会加载配置)

我的另一个问题是,我可以在全局级别访问一些对象和/或值,并在初始化控制器和操作时加载它们。据我所知,无法访问控制器的__construct中的服务管理器配置。

代码语言:javascript
复制
$this->getServiceLocator()->get('Config');

上面的方法不会起作用。我相信是因为在构建控制器类的过程中ServiceManager还不可用。合乎道理。

不过,只要多做几个步骤,我就可以像ZF1一样让preDispatch正常工作。然后配置的东西就可以工作了。以及对全局对象的访问,如数据库。

在控制器中添加以下方法:

代码语言:javascript
复制
protected function attachDefaultListeners()
{
    parent::attachDefaultListeners();
    $events = $this->getEventManager();
    $this->events->attach('dispatch', array($this, 'preDispatch'), 100);
    $this->events->attach('dispatch', array($this, 'postDispatch'), -100);
}

然后添加pre和post方法。

代码语言:javascript
复制
public function preDispatch (MvcEvent $e)
{
    // this is a db convenience class I setup in global.php
    // under the service_manager factories (will show below)
    $this->db = $this->getServiceLocator()->get('FBDb');
    // this is just standard config loaded from ServiceManager
    // set your property in your class for $config  (protected $config;)
    // then have access in entire controller
    $this->config = $this->getServiceLocator()->get('Config');
    // this comes from the things.config.local.php file
    echo "things boolvalue: " . $this->config['things']['boolvalue'];
}

public function postDispatch (MvcEvent $e)
{
    // Called after actions
}

问题2解决了!控制器的初始化。

3.如何将上述内容与ServiceManager结合使用,以加载在控制器中使用的DB对象

好吧,我最不想要的就是全局访问我的数据库。我希望它是控制器范围的,这样我就可以在任何地方调用$this->db->fetchAll。

首先在global.php中设置服务管理器。

另外,请记住,我不会将其完全保留在global.php文件中。但它现在起作用了。将这些数组添加到global.php中的返回数组中:

代码语言:javascript
复制
'db' => array(
    'driver' => 'Pdo',
    'dsn'   => 'mysql:dbname=mydb;host=localhost;',
    'username' => 'root',
    'password' => '',
    'driver_options' => array(
        PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
    ),

),
'service_manager' => array(
    'factories' => array(
        'Zend\Db\Adapter\Adapter'
                => 'Zend\Db\Adapter\AdapterServiceFactory',
        'db-adapter' => function($sm) {
                $config = $sm->get('config');
                $config = $config['db'];
                $dbAdapter = new Zend\Db\Adapter\Adapter($config);
                return $dbAdapter;
             },
        'FBDb'  => function($sm) {
                $dba= $sm->get('db-adapter');
                $db = new FBDb\Db($dba);
                return $db;
             },

    ),
),

在上面,我设置了数据库配置,然后service_manager有一些工厂,这些工厂在应用程序的其余部分需要的时候可以使用。在我的例子中,我希望能方便地向后兼容我的一些旧ZF1代码,所以我添加了一个名为FBDb的自定义模块。我发现了一个非常棒的包装器/桥接到zf1风格的db类,叫做ZFBridge,作者是Fabrizio Balliano。非常适合我的需求,你可以在这里找到:https://github.com/fballiano/zfbridge

我把它拿来,稍微修改了一下,然后做了一个模块。因此,FBDb对象在我的控制器中作为数据库连接可用。如果我想在其他地方使用它,也可以使用"db-adapter“。

无论如何,在我的控制器中,我在类的开头设置了"protected $db;“,这样我就可以使用这个属性了。然后,如上面的#2所示,我让preDispatch将此数据库对象分配给$ FBDb ->db。

代码语言:javascript
复制
$this->db = $this->getServiceLocator()->get('FBDb');

然后在我的操作方法中,如果我愿意,我可以调用一个记录集或db值,如下所示:

代码语言:javascript
复制
$sql = 'select * from customer where cust_nbr between ? and ?';
$rs = $this->db->fetchResults($sql, array('120400', '125250'));

或者,对于返回的数组:

代码语言:javascript
复制
$rs = $this->db->fetchAll($sql, array('120400', '125250'));

(我向ZFBridge添加了fetchResults,以便只从db查询返回PDO\Results对象,以便稍后在foreach中使用。)

我知道其中一些可能是糟糕的设计或“糟糕的OOP",但它对我来说很有效,我喜欢它。我个人不喜欢在所有事情上都使用纯对象的数据实体,只是一些事情。大多数时候,我只是想放入一个结果集并完成它。:)

问题解决了。就目前而言。如果您习惯于ZF1,那么现在可以让ZF2变得更加友好。

票数 18
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14128085

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档