問題
コントローラー名で次のようにサブ名前空間を使いたい場合、
Application/Controller/Admin/IndexController
<?php
namespace Application\Controller\Admin;
class IndexController extends \Zend\Mvc\Controller\AbstractActionController
{
public function indexAction()
{
return [];
}
}
次のようにルーティングするとテンプレートの名前が application/index/index.phtml
となってしまいます。
Application/config/module.config.php
return array(
'router' => array(
'routes' => array(
'home' => array(
'type' => 'literal',
'options' => array(
'route' => '/',
'defaults' => array(
'controller' => 'Application\Controller\Index',
'action' => 'index',
),
),
),
'admin' => array(
'type' => 'literal',
'options' => array(
'route' => '/admin',
'defaults' => array(
'controller' => 'Application\Controller\Admin\Index',
'action' => 'index',
),
),
),
),
),
// ...
);
Zend\Mvc\View\Http\InjectTemplateListener
でテンプレート名を解決するときに下記の2つが連結されてテンプレート名になるためです。
- コントローラーの先頭の名前空間(モジュール名)
- コントローラーの名前空間を除くクラス名からサフィックスの
Controller
を除いたもの
そのため、次の2つのコントローラーは同じテンプレート名になってしまいます。
Application\Controller\Index
-> application/index/{action}
Application\Controller\Admin\Index
-> application/index/{action}
解決方法
モジュールのブートストラップで Zend\Mvc\ModuleRouteListener
をアタッチします。
Application/Module.php
<?php
namespace Application;
use Zend\EventManager\EventInterface;
use Zend\Mvc\MvcEvent;
use Zend\ModuleManager\Feature\BootstrapListenerInterface;
use Zend\Mvc\ModuleRouteListener;
class Module implements BootstrapListenerInterface
{
public function onBootstrap(EventInterface $ev)
{
if ($ev instanceof MvcEvent) {
$ev->getApplication()->getEventManager()->attach(new ModuleRouteListener());
}
}
// ...
}
次のように __NAMESPACE__
を使ってルーティングを書きます。
Application/config/module.config.php
return array(
'router' => array(
'routes' => array(
'home' => array(
'type' => 'literal',
'options' => array(
'route' => '/',
'defaults' => array(
'__NAMESPACE__' => 'Application\Controller',
'controller' => 'Index',
'action' => 'index',
),
),
),
'admin' => array(
'type' => 'literal',
'options' => array(
'route' => '/admin',
'defaults' => array(
'__NAMESPACE__' => 'Application\Controller\Admin',
'controller' => 'Index',
'action' => 'index',
),
),
),
),
),
// ...
すると、テンプレート名の解決方法が次の3つを連結したものに変わります。
- コントローラーの先頭の名前空間(モジュール名)
-
__NAMESPACE__
で指定された名前空間の先頭2つを除いたもの - コントローラーの名前空間を除くクラス名からサフィックスの
Controller
を除いたもの
よって、次の2つも別々のテンプレートになります。
Application\Controller\Index
-> application/index/{action}
Application\Controller\Admin\Index
-> application/admin/index/{action}