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
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',
),
),
/* ... */
);
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
Related
I am new in Zend Frameworkâ 2 . i have downloaded zend-skeleton application its working fine.but when i created new module of album & calling album route page not found error(404) occurs .
I have tried to apply many types of zf2 routes but same error message.
This is the error page which is being displayed again & again when i access album route :
I don't know why this error is being occurred? Kindly suggest me any solution?
Try to check your Module.php it should look something like this
public function getConfig()
{
return include __DIR__ . '/config/module.config.php';
}
public function getAutoloaderConfig()
{
return array(
'Zend\Loader\StandardAutoloader' => array(
'namespaces' => array(
__NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__,
),
),
);
}
especially check namespace in all module files
your module.config.php should look like this
'controllers' => array(
'invokables' => array(
'index' => 'Album\Controller\IndexController',
),
),
'router' => array(
'routes' => array(
'album' => array(
'type' => 'literal',
'options' => array(
'route' => '/album',
'defaults' => array(
'controller' => 'index',
'action' => 'index',
),
),
),
),
),
'view_manager' => array(
'template_path_stack' => array(
'album' => __DIR__ . '/../view',
),
),
I hope, it will help you.
I'm new with Zend Framework, i used to use framework CI and Laravel but in my project i should use ZF2. Honestly, i don't get it how to building app with ZF2. I followed the instructions from here : https://www.youtube.com/watch?v=OYkVHiXeGeY
but i got some error.
Zend\Mvc\Controller\ControllerManager::createFromInvokable: failed retrieving "csnusercontrolleruser(alias: CsnUser\Controller\User)" via invokable class "CsnUser\Controller\UserController"; class does not exist
my strucktur folder:
:: module
->CsnUser
>>config
->module.config.php
>>src
->CsnUser
->Controller
->UserController.php
>>view
->csn-user
->user
->index.phtml
>>Module.php
Module.php
<?php
namespace CsnUser;
use Zend\ModuleManager\Feature\AutoloaderProviderInterface;
use Zend\ModuleManager\Feature\ConfigProviderInterface;
class Module{
public function getConfig()
{
return include __DIR__ . '/config/module.config.php';
}
public function getAutoloaderConfig()
{
return array(
'Zend\Loader\StandardAutoloader' => array(
'namespace' => array(
__NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__,
),
),
);
}
}
module.config.php
<?php
return array(
'controllers' => array(
'invokables' => array(
'CsnUser\Controller\User' => 'CsnUser\Controller\UserController',
),
),
'router' => array(
'routes' => array(
'csn_user' => array(
'type' => 'Literal',
'options' => array(
'route' => '/csn-user',
'defaults' => array(
'__NAMESPACE__' => 'CsnUser\Controller',
'controller' => 'User',
'action' => 'index',
),
),
'may_terminate' => true,
'child_routes' => array(
'default' => array(
'type' => 'Segment',
'options' => array(
'route' => '/[:controller[/:action[/:id]]]',
'constraints' => array(
'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]*',
),
'defaults' => array(),
),
),
),
),
),
),
'view_manager' => array(
/*'template_map' => array(
'layout/Auth' => __DIR__ . '/../view/layout/xxxx.phtml',
),*/
'template_path_stack' => array(
'csn_user' => __DIR__ . '/../view'
),
),
);
UserController.php
<?php
namespace CsnUser\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
class UserController extends AbstractActionController{
public function indexAction()
{
return new ViewModel();
}
}
index.phtml
<h1>Welcome</h1>
Can anyone help me ?
Your getAutoLoaderConfig() method is incorrect.
Try this once:
public function getAutoloaderConfig()
{
return array(
'Zend\Loader\StandardAutoloader' => array(
'namespaces' => array(
__NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__,
),
),
);
}
Pay attention to the key namespaces in the array.
In your instruction video at 4:40 they also use the plural :)
I solved the problem by adding a string to composer.json:
"autoload": {
"psr-0": {
"MyModule": "module/MyModule/src/"
}
}
and then, in the console, I navigated to the project folder and ran:
php composer.phar update
First create a folder coinsproject then,
coinsproject-->config folder,src folder,view folder,autoload_classmap.php,Module.php
In Coinsproject/autoload_classmap.php
<?php
return array();
?>
In Coinsproject/Module.php
<?php
namespace Coinsproject;
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 getConfig()
{
return include __DIR__ . '/config/module.config.php';
}
}
?>
In Coinsproject/config/module.config.php
<?php
return array(
'controllers' => array(
'invokables' => array(
'Coinsproject\Controller\Coinsproject' => 'Coinsproject\Controller\CoinsprojectController',
),
),
'router' => array(
'routes' => array(
'album' => array(
'type' => 'segment',
'options' => array(
'route' => '/coinsproject[/][:action][/:id]',
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
),
'defaults' => array(
'controller' => 'Coinsproject\Controller\Coinsproject',
'action' => 'index',
),
),
),
),
),
'view_manager' => array(
'template_path_stack' => array(
'coinsproject' => __DIR__ . '/../view',
),
),
);
?>
In Coinsproject/src/Coinsproject/Controller/CoinsprojectController.php
<?php
namespace Coinsproject\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
class CoinsprojectController extends AbstractActionController
{
public function indexAction()
{
return new ViewModel();
}
}
?>
In Coinsproject/view/coinsproject/coinsproject/index.phtml
<html>
my name is swapnil.
</html>
And after that i call my module in root/config/application.config.php but when i run it its not working anything.Where i did my mistakes?
In Coinsproject/config/module.config.php
'routes' => array(
'album' => array(
to
'routes' => array(
'coinsproject' => array(
you forget to change the route into coinsproject first, i don't know if it's the only correction to make, but it's a beginning.
may be you should put index.phtml in
Coinsproject/view/coinsproject/index.phtml
[Modulename]/view/[Controllername]/[actionname].phtml
not in
Coinsproject/view/coinsproject/coinsproject/index.phtml
and try to correct define view script (phtml file) in module.config.php in view_manager
'view_manager' => array(
'template_map' => array(
coinsproject/coinsproject/index => __DIR__ . '/../view/coinsproject/index.phtml
)
)
I'm currently learning Zend2. My first attempt is create secured application with basic login form. So my first idea was to create a common SecuredController, that checks for user identity in his constructor and redirects if necessary. I saw that solution for Zend1 and was working:
class SecuredController extends AbstractActionController
{
function __construct()
{
$auth = new AuthenticationService();
if ( $auth->hasIdentity() ) {
return $this->redirect()->toRoute("ts");
}
return $this->redirect()->toRoute( "login" );
}
}
Then extending some other controllers used throughout appliation:
class MainController extends SecuredController
{
public function indexAction()
{
return new ViewModel();
}
}
I omitted LoginController and IndexController(same as MainController now), but you get the idea how it is set up. Confing for module looks like this:
<?php
namespace Main;
return array(
'controllers' => array(
'invokables' => array(
'Main\Controller\Secured' => 'Main\Controller\Common\SecuredController',
'Main\Controller\Login' => 'Main\Controller\LoginController',
'Main\Controller\Main' => 'Main\Controller\MainController',
'Main\Controller\Index' => 'Main\Controller\IndexController',
),
),
'router' => array(
'routes' => array(
'home' => array(
'type' => 'Zend\Mvc\Router\Http\Literal',
'options' => array(
'route' => '/',
'defaults' => array(
'controller' => 'Main\Controller\Index',
'action' => 'index',
),
),
),
'main' => array(
'type' => 'segment',
'options' => array(
'route' => '/ts[/][:action]',
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
),
'defaults' => array(
'controller' => 'Main\Controller\Main',
'action' => 'index',
),
),
),
'login' => array(
'type' => 'Zend\Mvc\Router\Http\Literal',
'options' => array(
'route' => '/login',
'defaults' => array(
'controller' => 'Main\Controller\Login',
'action' => 'login',
),
),
),
'logout' => array(
'type' => 'Zend\Mvc\Router\Http\Literal',
'options' => array(
'route' => '/logout',
'defaults' => array(
'controller' => 'Main\Controller\Login',
'action' => 'logout',
),
),
),
),
),
'view_manager' => array(
'display_not_found_reason' => true,
'display_exceptions' => true,
'doctype' => 'HTML5',
'not_found_template' => 'error/404',
'exception_template' => 'error/index',
'template_map' => array(
'layout/login' => __DIR__ . '/../view/layout/login.phtml',
'layout/layout' => __DIR__ . '/../view/layout/layout.phtml',
'application/index/index' => __DIR__ . '/../view/main/index/index.phtml',
'error/404' => __DIR__ . '/../view/error/404.phtml',
'error/index' => __DIR__ . '/../view/error/index.phtml',
),
'template_path_stack' => array(
__DIR__ . '/../view',
),
),
'doctrine' => array(
'driver' => array(
__NAMESPACE__ . '_driver' => array(
'class' => 'Doctrine\ORM\Mapping\Driver\AnnotationDriver',
'cache' => 'array',
'paths' => array( __DIR__ . '/../src/' . __NAMESPACE__ . '/Entity' )
),
'orm_default' => array(
'drivers' => array(
__NAMESPACE__ . '\Entity' => __NAMESPACE__ . '_driver'
)
)
)
),
);
But unfortunately its not working I have error:
Url plugin requires that controller event compose a router; none found
Anyone has a clue how implement my scenario? Securing whole aplication and redirecting to /login route users without identity.
Add in your super controller.
namespace Admin\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\Authentication\AuthenticationService;
...
class AdminController extends AbstractActionController
{
public function onDispatch(\Zend\Mvc\MvcEvent $e)
{
/**
* Verifica se o usuario se encontra logado, caso contrario redirecion ele para o login
*/
$this->authService = new AuthenticationService();
if(!$this->authService->hasIdentity()){
$this->redirect()->toRoute("login");
}
return parent::onDispatch($e);
}
...
}
I believe this will work in your project design.
issue 1)
return $this->redirect()->toRoute("ts");
You don't have a route named 'ts' in your config, you need to setup the route when using toRoute().
issue 2)
You aren't setting up AuthenticationService properly. You need to specify an adapter to use this.
Instead of instantiating it in the controller, define it in your ServiceManager config.
config:
'My\AuthService' => function($sm) {
$auth = new \Zend\Authentication\AuthenticationService();
$auth->setAdatper(/** LDAP or What ever **/);
return $auth;
},
controller:
// already setup for you in the service manager
$authService = $this->getServiceLocator()->get('My\AuthService');
You could always try zfcUser module if you want something out of the box tyo allow registering users etc:
https://github.com/ZF-Commons/ZfcUser
Authentication Module width login page
I'm trying to learn Zend Framework 2 and currently facing an issue.
I have created a module named "Admin" and have defined layout for Admin Module. Now problem is Application module is also loading Admin Module's layout. If I browse Admin or Application module, same layout is being loaded. I have tried multiple solutions by Googling but didn't get anyone working.
I have created Admin module by copying Application module dir and renaming it to Admin and changed "Application" to "Admin" in sub directories name and code files.
This is the visual presentation of Khalids post with one more addition in the config/application.config.php file
Step 1.
Step 2.
Copy Application Module to and rename to Admin
//config/application.config.php
'modules' => array(
'Application'
,'Test', // add this line
),
<?php
//Step 3.
//your Test/config/module.config.php should look like as follows
return array(
'router' => array(
'routes' => array(
/* 'home' => array(
'type' => 'Zend\Mvc\Router\Http\Literal',
'options' => array(
'route' => '/',
'defaults' => array(
// 'controller' => 'StickyNotes\Controller\Album',
//'controller' => 'Application\Controller\Index',
'action' => 'index',
),
),
), */
// The following is a route to simplify getting started creating
// new controllers and actions without needing to create a new
// module. Simply drop new controllers in, and you can access them
// using the path /application/:controller/:action
'application' => array(
'type' => 'Literal',
'options' => array(
'route' => '/test',
'defaults' => array(
'__NAMESPACE__' => 'Test\Controller',
'controller' => 'Index',
'action' => 'index',
),
),
'may_terminate' => true,
'child_routes' => array(
'default' => array(
'type' => 'Segment',
'options' => array(
'route' => '/[:controller[/:action]]',
'constraints' => array(
'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
),
'defaults' => array(
),
),
),
),
),
),
),
'service_manager' => array(
'factories' => array(
'translator' => 'Zend\I18n\Translator\TranslatorServiceFactory',
),
),
'translator' => array(
'locale' => 'en_US',
'translation_file_patterns' => array(
array(
'type' => 'gettext',
'base_dir' => __DIR__ . '/../language',
'pattern' => '%s.mo',
),
),
),
'controllers' => array(
'invokables' => array(
'Test\Controller\Index' => 'Test\Controller\IndexController',
),
),
'view_manager' => array(
'display_not_found_reason' => true,
'display_exceptions' => true,
'doctype' => 'HTML5',
'not_found_template' => 'error/404',
'exception_template' => 'error/index',
'template_map' => array(
'layout/test' => __DIR__ . '/../view/layout/test.phtml',
'application/index/index' => __DIR__ . '/../view/test/index/index.phtml',
'error/404' => __DIR__ . '/../view/error/404.phtml',
'error/index' => __DIR__ . '/../view/error/index.phtml',
),
'template_path_stack' => array(
__DIR__ . '/../view',
),
),
);
Step 4.
and finally your Test/Module file should look as follows:->
namespace Test;
use Zend\Mvc\ModuleRouteListener;
use Zend\Mvc\MvcEvent;
class Module
{
public function onBootstrap(MvcEvent $e)
{
$e->getApplication()->getServiceManager()->get('translator');
$eventManager = $e->getApplication()->getEventManager();
$moduleRouteListener = new ModuleRouteListener();
$moduleRouteListener->attach($eventManager);
}
public function getConfig()
{
return include __DIR__ . '/config/module.config.php';
}
public function getAutoloaderConfig()
{
return array(
'Zend\Loader\StandardAutoloader' => array(
'namespaces' => array(
__NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__,
),
),
);
}
}
and you will be ready to roll.
Well, at last I have found a solution.
Suppose you want to create a module named "Admin", here are the steps:
1- Copy Application Module Dir and rename it to "Admin". It is the name of your module.
2- Update all references in Admin Module that are initially pointing towards Application module. ( change "Application" to "Application" and "application" to "admin" )
3- In Admin/config/module.config.php remove "home" route.
4- Update your layout and views.
5- Test in your browser by using http://example.com/admin
That's it.
You don't need any external layout lib like "EdpModuleLayouts"
Cheers :)