是否可以在Module.php中创建变量甚至共享对象(如DB适配器),以便在所有视图控制器中使用?(Zend Framework 2)
例如:
class Module
{
public function onBootstrap(MvcEvent $e)
{
$moduleConfig = $e->getServiceManager()->get('Config')
}
}在控制器中,以某种方式访问,使用:
$this->moduleConfig['db']在上面,我知道这只是db适配器的配置数组,但它是如何工作的呢?
我看到可以在控制器操作中做到这一点:
$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中确实有这个(不,它没有停留在那里,只是举个例子):
'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中所示。
感谢您的指导!谢谢!
发布于 2013-01-04 03:34:06
好吧..。多部分答案。
1.添加站点范围的配置变量。(以及如何在控制器中访问)
这很简单,当我看到它工作的时候。但这取决于下面的preDispatch。在您的应用程序根目录中,将一个文件放入config/autoload。取名为: things.config.local.php
在这个文件中,我们只返回一个带有配置项的数组。
<?php
return array(
'things' => array(
'avalue' => 'avalue1',
'boolvalue' => true,
),
);所以我想在我的控制器中访问它。假设您在控制器中创建了一个config属性,您可以这样访问它。(您可以在下面的preDispatch中设置该属性以使其正常工作)在我的系统中,我更喜欢这样检索该值:
$this->config['things']['boolvalue'];但是,您可以在如下所示的操作中调用它:
$config = $this->getServiceLocator()->get('Config');
echo $config['things']['boolvalue'];实际上,这很容易。不确定如何使用ini文件,但在我的例子中,不需要这样做,并且我的ini文件直接移到数组中并不是什么大问题。问题1为我解决了!
2.如何在控制器中获取preDispatch (因为__construct不会加载配置)
我的另一个问题是,我可以在全局级别访问一些对象和/或值,并在初始化控制器和操作时加载它们。据我所知,无法访问控制器的__construct中的服务管理器配置。
$this->getServiceLocator()->get('Config');上面的方法不会起作用。我相信是因为在构建控制器类的过程中ServiceManager还不可用。合乎道理。
不过,只要多做几个步骤,我就可以像ZF1一样让preDispatch正常工作。然后配置的东西就可以工作了。以及对全局对象的访问,如数据库。
在控制器中添加以下方法:
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方法。
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中的返回数组中:
'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。
$this->db = $this->getServiceLocator()->get('FBDb');然后在我的操作方法中,如果我愿意,我可以调用一个记录集或db值,如下所示:
$sql = 'select * from customer where cust_nbr between ? and ?';
$rs = $this->db->fetchResults($sql, array('120400', '125250'));或者,对于返回的数组:
$rs = $this->db->fetchAll($sql, array('120400', '125250'));(我向ZFBridge添加了fetchResults,以便只从db查询返回PDO\Results对象,以便稍后在foreach中使用。)
我知道其中一些可能是糟糕的设计或“糟糕的OOP",但它对我来说很有效,我喜欢它。我个人不喜欢在所有事情上都使用纯对象的数据实体,只是一些事情。大多数时候,我只是想放入一个结果集并完成它。:)
问题解决了。就目前而言。如果您习惯于ZF1,那么现在可以让ZF2变得更加友好。
https://stackoverflow.com/questions/14128085
复制相似问题