Before
Zend Framework 2 のチュートリアルを進めていくと、AlbumTable クラスのコンストラクタで TableGateway を引数に取り、Module の ServiceConfig で ファクトリを使って AlbumTable に TableGateway を注入することになります。
module/Album/src/Album/Model/AlbumTable.php
<?php
namespace Album\Model;
use Zend\Db\TableGateway\TableGateway;
class AlbumTable
{
protected $tableGateway;
public function __construct(TableGateway $tableGateway)
{
$this->tableGateway = $tableGateway;
}
// (snip)
}
module/Album/Module.php
<?php
namespace Album;
use Album\Model\Album;
use Album\Model\AlbumTable;
use Zend\Db\ResultSet\ResultSet;
use Zend\Db\TableGateway\TableGateway;
class Module
{
// (snip)
public function getServiceConfig()
{
return array(
'factories' => array(
'Album\Model\AlbumTable' => function($sm) {
$tableGateway = $sm->get('AlbumTableGateway');
$table = new AlbumTable($tableGateway);
return $table;
},
'AlbumTableGateway' => function ($sm) {
$dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
$resultSetPrototype = new ResultSet();
$resultSetPrototype->setArrayObjectPrototype(new Album());
return new TableGateway('album', $dbAdapter, null, $resultSetPrototype);
},
),
);
}
}
Use initializer by closure
AlbumTableGateway がサービスとして定義されている意義をあまり感じないので、サービスのイニシャライザで AlbumTable に DbAdapter を直接注入し、TableGateway は AlbumTable の中で作るようにします。
イニシャライザについての説明は下記がわかりやすいです。
AlbumTable に AdapterAwareInterface をインプリメントして AdapterAwareInterface::setDbAdapter の実装に Module の getServiceConfig に書いていた処理をごっそり移します。
また、AlbumTable のコンストラクタはもう不用なので削除します。
module/Album/src/Album/Model/AlbumTable.php
<?php
namespace Album\Model;
use Zend\Db\TableGateway\TableGateway;
use Zend\Db\ResultSet\ResultSet;
use Zend\Db\Adapter\Adapter;
use Zend\Db\Adapter\AdapterAwareInterface;
class AlbumTable implements AdapterAwareInterface
{
protected $tableGateway;
public function setDbAdapter(Adapter $adapter)
{
$resultSetPrototype = new ResultSet();
$resultSetPrototype->setArrayObjectPrototype(new Album());
$this->tableGateway = new TableGateway('album', $adapter, null, $resultSetPrototype);
}
// (snip)
}
Module の getServiceConfig で initializers と AlbumTable を定義します。
AlbumTable にはもう特別なファクトリは必要ないので invokables で定義します。
initializers はサービスのインスタンス化の際に自動的に呼ばれる処理です。
この例ではサービスのインスタンスが AdapterAwareInterface をインプリメントしているかどうかを調べ、インプリメントしているなら DbAdapter をサービスマネージャから取り出してセットします。
module/Album/Module.php
<?php
namespace Album;
use Zend\Db\Adapter\AdapterAwareInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
class Module
{
// (snip)
public function getServiceConfig()
{
return array(
'invokables' => array(
'Album\Model\AlbumTable' => 'Album\Model\AlbumTable',
),
'initializers' => array(
function ($instance, ServiceLocatorInterface $sm) {
if ($instance instanceof AdapterAwareInterface)
{
$instance->setDbAdapter($sm->get('Zend\Db\Adapter\Adapter'));
}
}
),
);
}
}
implement InitializerInterface
上の例ではイニシャライザをクロージャーで実装しましたが、InitializerInterface をインプリメントしたクラスでも可能です。
次のように InitializerInterface を実装したクラスを作ります。やっていることは上の例のクロージャーと同じです。
module/Album/src/Album/Db/Adapter/AdapterInitializer.php
<?php
namespace Album\Db\Adapter;
use Zend\ServiceManager\InitializerInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\Db\Adapter\AdapterAwareInterface;
class AdapterInitializer implements InitializerInterface
{
public function initialize($instance, ServiceLocatorInterface $serviceLocator)
{
if ($instance instanceof AdapterAwareInterface)
{
$instance->setDbAdapter($serviceLocator->get('Zend\Db\Adapter\Adapter'));
}
}
}
Module の getServiceConfig の initializers でイニシャライザのクラスを指定します。
module/Album/Module.php
<?php
namespace Album;
class Module
{
// (snip)
public function getServiceConfig()
{
return array(
'invokables' => array(
'Album\Model\AlbumTable' => 'Album\Model\AlbumTable',
),
'initializers' => array(
'Album\Db\Adapter\AdapterInitializer',
),
);
}
}
getServiceConfig の中身がかなりスッキリしました。