LoginSignup
6
6

More than 5 years have passed since last update.

ZF2のコントローラーでサブ名前空間を使う

Last updated at Posted at 2014-07-29

問題

コントローラー名で次のようにサブ名前空間を使いたい場合、

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つが連結されてテンプレート名になるためです。

  1. コントローラーの先頭の名前空間(モジュール名)
  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つを連結したものに変わります。

  1. コントローラーの先頭の名前空間(モジュール名)
  2. __NAMESPACE__ で指定された名前空間の先頭2つを除いたもの
  3. コントローラーの名前空間を除くクラス名からサフィックスの Controller を除いたもの

よって、次の2つも別々のテンプレートになります。

Application\Controller\Index
 -> application/index/{action}
Application\Controller\Admin\Index
 -> application/admin/index/{action}
6
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6