Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple namespaces under same module in ZF2

I'm having trouble configuring multiple namespaces/classes under same module. For example, I have a module called "Account", in which I'd like to include all account related classes (companies: 'accounts', users: 'users', external api: 'api' etc.. ). Module structure looks like this..

        /Account
        - Module.php
        - /config
        - /view
        - /src
          - /Account
            - /Controller (AccountController.php)
            - /Form       (AccountForm.php)
            - /Model      (Account.php + AccountTable.php)
          - /User
            - /Controller (UserController.php)
            - /Form       (UserForm.php)
            - /Model      (User.php + UserTable.php)
          - /Api
            - Api.php     (simple class)

Being new to ZF2, I decided to keep things simple and stupid and Not to try implementing complex routing to Account module. So, in order to trigger indexAction for UserController, url should be /user (!)

Here's the module class:

namespace Account;

use Account\Model\AccountTable;
use Account\Model\UserTable;

class Module
{
    public function getAutoloaderConfig()
    {
        return array(
                            'Zend\Loader\ClassMapAutoloader' => array(
                                                                                        __DIR__ . '/autoload_classmap.php',
                                                                                  ),
                            'Zend\Loader\StandardAutoloader' => array(
                                                                                        'namespaces' => array(
                                                                                                                        __NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__,
                                                                                                                    ),
                                                                               ),
        );
    }

    public function getServiceConfig()
    {
        return array(
                            'factories' => array(
                                                            'Account\Model\AccountTable'  =>  function($sm) {
                                                                                                                                $dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
                                                                                                                                $table = new AccountTable($dbAdapter);
                                                                                                                                return $table;
                                                                                                                            },
                                                            'Account\Model\UserTable'           =>  function($sm) {
                                                                                                                                $dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
                                                                                                                                $table = new UserTable($dbAdapter);
                                                                                                                                return $table;
                                                                                                                            },                                                              
                                                      ),
        );
    }    

    public function getConfig()
    {
        return include __DIR__ . '/config/module.config.php';
    }
}

And the module.config file

return array(
    'controllers' => array(
        'invokables' => array(
            'Account\Controller\Account'    => 'Account\Controller\AccountController',
            'Account\Controller\User'           => 'Account\Controller\UserController',
        ),
    ),

    'router' => array(
        'routes' => array(
            'account' => array(
                'type'    => 'segment',
                'options' => array(
                    'route'      => '/account[/:action[/:accountId]]',
                    'constraints' => array(
                                                    'action'         => '[a-zA-Z][a-zA-Z0-9_-]*',
                                                    'accountId'      => '[0-9]+',
                                                ),
                    'defaults' => array(
                        'controller' => 'Account\Controller\Account',
                        'action'     => 'index',
                    ),
                ),
/*
                'may_terminate' => true,
                'child_routes' => array(
                      'user' => array(
                            'type' => 'literal',
                            'options' => array(
                                'route' => '/user[/:action[/:userId]]',
                                'constraints' => array(
                                                    'action'         => '[a-zA-Z][a-zA-Z0-9_-]*',
                                                    'userId'         => '[0-9]+',
                                                ),
                                'defaults' => array(
                                        'controller' => 'Account\Controller\User',
                                        'action'     => 'index'
                                )
                        )
                    )
                ),
*/
            ),
            'user' => array(
                'type'    => 'segment',
                'options' => array(
                    'route'      => '/user[/:action[/:userId]]',
                    'constraints' => array(
                                                    'action'     => '[a-zA-Z][a-zA-Z0-9_-]*',
                                                    'userId'     => '[0-9]+',
                                                ),
                    'defaults' => array(
                        'controller' => 'Account\Controller\User',
                        'action'     => 'index',
                    ),
                ),
             )


        ),
    ),

    'view_manager' => array(
        'template_path_stack' => array(
            'account' => __DIR__ . '/../view',
            'user'    => __DIR__ . '/../view',

        ),
    ),
);

But the error I'm getting is, "Class 'Account\Controller\UserController' not found". I am sure i've missed something. Any clue please?

Thanks

like image 315
J A Avatar asked Apr 03 '13 01:04

J A


2 Answers

You must let the StandardAutoloader know about your new namespace:

public function getAutoloaderConfig()
{
    return array(
        'Zend\Loader\ClassMapAutoloader' => array(
            __DIR__ . '/autoload_classmap.php',
        ),
        'Zend\Loader\StandardAutoloader' => array(
            'namespaces' => array(
                // This is for the Account namespace
                __NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__,
                // And this is for the User namespace
                'User'        => __DIR__ . '/src/' . 'User',
            ),
        ),
    );
}

In the module.config.php

return array(
    'controllers' => array(
        'invokables' => array(
            'Account\Controller\Account' => 'Account\Controller\AccountController',
            // The key can be what ever you want, but the value must be a valid
            // class name. Your UserController lives in the User namespace,
            // not in Account
            'Account\Controller\User'    => 'User\Controller\UserController',
        ),
    ),
    /* ... */
);
like image 65
Josias Iquabius Avatar answered Sep 29 '22 21:09

Josias Iquabius


The StandardLoader needs to know where to find the classes. You can define it with an option called namespaces which is an array that contains absolute (or relative to the current script) paths. It should look like this:

'Zend\Loader\StandardAutoloader' => array(
    'namespaces' => array(
        __NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__
    ) 
) 

__NAMESPACE__ is the name of the module, and __DIR__ the absolute path to the Module.php script

Check http://framework.zend.com/manual/2.0/en/modules/zend.loader.standard-autoloader.html

The ClassMapAutoloader is used for performance: you define the class key and its exactly path to the file, instead of a folder which zf2 has to browse its contents doing filesystem operations (StandardLoader's way).

Check http://framework.zend.com/manual/2.0/en/modules/zend.loader.class-map-autoloader.html

like image 30
lluisaznar Avatar answered Sep 29 '22 21:09

lluisaznar