好的...多部分答案。
1.添加配置变量,站点范围。(以及如何在控制器中访问)
这很容易,一旦我看到它起作用。但取决于下面的 preDispatch。在您的应用程序根目录中,将文件放入 config/autoload. 调用它:things.config.local.php
在这个文件中,我们只返回一个带有配置项的数组。
<?php
return array(
'things' => array(
'avalue' => 'avalue1',
'boolvalue' => true,
),
);
所以我想在我的控制器中访问它。假设您在控制器中创建了一个配置属性,您可以通过这种方式访问它。(您在下面的 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 还不可用。说得通。
不过,还有几个额外的步骤,我可以让 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);
}
然后添加 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对象供Controller使用
好的,我想要的最后一件事是全局访问我的数据库。我希望它在控制器范围内,所以我可以在任何地方调用 $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;
},
),
),
在上面,我设置了 db 配置,然后 service_manager 有一些工厂,这些工厂在应用程序的其余部分需要时可用。就我而言,我想要一些方便以向后兼容我的一些旧 ZF1 代码,所以我添加了一个名为 FBDb 的自定义模块。我发现了 Fabrizio Balliano 的一个很棒的 wrapper/bridge-to-zf1-style-db 类,叫做 ZFBridge。非常适合我的需求,您可以在这里找到:
https ://github.com/fballiano/zfbridge
我接受了它,对其进行了一些修改,然后制作了一个模块。所以 FBDb 对象在我的控制器中作为我的数据库连接可用。如果我想在其他地方使用它,则与“db-adapter”相同。
无论如何,在我的控制器中,我设置了“受保护的 $db;” 在课程开始时,我可以使用该属性。然后如上面的#2 所示,我有 preDispatch 将 FBDb 数据库对象分配给 $this->db。
$this->db = $this->getServiceLocator()->get('FBDb');
然后在我的操作方法中,如果需要,我可以使用以下命令调用记录集或数据库值:
$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'));
(我将 fetchResults 添加到 ZFBridge 以仅从 db 查询中返回 PDO\Results 对象,以便稍后在 foreach 中使用。)
我知道其中一些可能是糟糕的设计或“糟糕的 OOP”,但它对我有用,我喜欢它。我个人不喜欢使用纯基于对象的数据实体来处理所有事情,只是一些事情。很多时候,我只想放入一个结果集并完成它。:)
问题解决了。目前。如果你习惯了 ZF1,现在让 ZF2 变得更加友好。