gre*_*eek 5 php zend-framework2
是否可以在Module.php中创建变量甚至共享对象(如DB适配器),以便在所有视图控制器中使用?(Zend Framework 2)
例如:
class Module
{
public function onBootstrap(MvcEvent $e)
{
$moduleConfig = $e->getServiceManager()->get('Config')
}
}
Run Code Online (Sandbox Code Playgroud)
在控制器中,以某种方式访问使用:
$this->moduleConfig['db']
Run Code Online (Sandbox Code Playgroud)
在上面我知道这只是数据库适配器的配置数组,但它怎么会工作?
我看到一个人可以在控制器动作中执行此操作:
$config = $this->getServiceLocator()->get('Config')
$dba = new DbAdapter($config['db']);
Run Code Online (Sandbox Code Playgroud)
我不想在每个需要配置的地方都这样做.我怎么能这样做:$ this-> config ?? 所以它适用于所有行动.更好的是,如何在整个模块中做到这一点?我知道我这一切都错了,但在ZF1中我们有Zend_Registry :: get()这样的简单事情.我正在阅读文档和各种各样的文章,但总是有一些假设,我只是迷路了.所以我真正想要的是:A)全球可访问的配置项,B)全局可访问的数据库适配器
我只想在我的控制器中调用$ this-> db或$ this-> config-> item.这可能吗?我知道我错过了一些非常简单的事情.
我也尝试使用$ this-> getServiceLocator() - > get('Config')在我的__construct中设置$ this-> config; 但我知道服务定位器在构造期间尚不可用.我尝试通过在模块的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\''
),
),
Run Code Online (Sandbox Code Playgroud)
我可以使用getServiceLocator()在任何操作中访问该项和其他项.我希望这些项目可用作我的控制器属性,如$ this-> config-> item.
我感谢任何指导!谢谢!
gre*_*eek 18
好的...多部分回答.
一旦我看到它工作,这很容易.但取决于下面的preDispatch.在您的应用根目录中,将文件放入config/autoload中.叫它:things.config.local.php
在这个文件中,我们只返回一个包含配置项的数组.
<?php
return array(
'things' => array(
'avalue' => 'avalue1',
'boolvalue' => true,
),
);
Run Code Online (Sandbox Code Playgroud)
所以我希望在我的控制器中访问它.假设您在控制器中创建了一个配置属性,您可以通过这种方式访问它.(您在下面的preDispatch中设置了该属性以使其工作)在我的系统中,我更喜欢检索该值,如下所示:
$this->config['things']['boolvalue'];
Run Code Online (Sandbox Code Playgroud)
但是,你可以在这样的动作中调用它:
$config = $this->getServiceLocator()->get('Config');
echo $config['things']['boolvalue'];
Run Code Online (Sandbox Code Playgroud)
实际上这很容易.不知道怎么做,有一个ini文件,但在我的情况下,它不需要和我的INI文件不能也不是什么大不了直接进入阵列.问题1为我解决了!
我的另一个问题是我可以在全局级别访问某些对象和/或值,并在初始化控制器和操作时加载它们.据我了解,它不可能访问控制器的__construct中的服务管理器配置.
$this->getServiceLocator()->get('Config');
Run Code Online (Sandbox Code Playgroud)
以上不起作用.我相信因为在构造控制器类期间ServiceManager尚不可用.说得通.
除了几个额外的步骤,我可以使preDispatch工作,类似于ZF1. 然后配置的东西工作.以及访问全局对象,如数据库.
在控制器中添加以下方法:
protected function attachDefaultListeners()
{
parent::attachDefaultListeners();
$events = $this->getEventManager();
$this->events->attach('dispatch', array($this, 'preDispatch'), 100);
$this->events->attach('dispatch', array($this, 'postDispatch'), -100);
}
Run Code Online (Sandbox Code Playgroud)
然后添加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
}
Run Code Online (Sandbox Code Playgroud)
问题2解决了!Init为控制器.
好的,我想要的最后一件事是全局访问我的数据库.我希望它在控制器范围内,所以我可以在任何地方调用$ 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;
},
),
),
Run Code Online (Sandbox Code Playgroud)
在上面,我设置了db config,然后service_manager有一些工厂,这些工厂在应用程序的其余部分需要时可用.在我的情况下,我想要一些方便的向后兼容我的一些旧的ZF1代码,所以我添加了一个名为FBDb的自定义模块.我发现了Fabrizio Balliano的一个名为ZFBridge的奇妙包装/桥接到zf1风格的db类.我的工作非常适合您的需求,您可以在这里找到:https: //github.com/fballiano/zfbridge
我拿了它,修改了一下,并制作了一个模块.因此FBDb对象在我的控制器中可用作我的数据库连接.与"db-adapter"相同,如果我想在其他地方使用它.
无论如何,在我的控制器中,我设置了"protected $ db;" 在课程开始时,我有这个属性.然后如上面的#2所示,我有preDispatch将FBDb数据库对象分配给$ this-> db.
$this->db = $this->getServiceLocator()->get('FBDb');
Run Code Online (Sandbox Code Playgroud)
然后在我的动作方法中,如果我想,我可以使用以下方法调用记录集或db值:
$sql = 'select * from customer where cust_nbr between ? and ?';
$rs = $this->db->fetchResults($sql, array('120400', '125250'));
Run Code Online (Sandbox Code Playgroud)
或者,对于返回的数组:
$rs = $this->db->fetchAll($sql, array('120400', '125250'));
Run Code Online (Sandbox Code Playgroud)
(我将fetchResults添加到ZFBridge以仅返回PDO\Results对象形成db查询以便稍后在foreach中使用.)
我知道其中一些可能是糟糕的设计或"糟糕的OOP",但它对我有用,我喜欢它.我个人不会使用基于纯对象的数据实体来处理所有事情,只是一些事情.很多时候,我只想放弃一个结果集并完成它.:)
问题解决了.目前.如果你已经习惯了ZF1,那么现在让ZF2更加友好.