I hope someone can help me with this.
I am working my way through Rob Allen's Zend Framework 2 Tutorial .
When I try to go to:
http://zf2-tutorial.localhost/album
I get the following error in apache's log (i using Zend Server CE version free):
PHP Fatal error: Class 'Album\Controller\AlbumController' not found in C:\Program Files\Zend\Apache2\htdocs\zf2-tutorial\vendor\zendframework\zendframework\library\Zend\ServiceManager\AbstractPluginManager.php on line 175
module\Album\module.config.php
<?php
return array(
'controllers' => array(
'invokables' => array(
'Album\Controller\Album' => 'Album\Controller\AlbumController'
),
),
'router' => array(
'routes' => array(
'album' => array(
'type' => 'segment',
'options' => array(
'route' => '/album[/:action][/:id]',
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
),
'defaults' => array(
'controller' => 'Album\Controller\Album',
'action' => 'index',
),
),
),
),
),
'view_manager' => array(
'template_path_stack' => array(
'album' => __DIR__ . '/../view'
)
)
);
module\Album\src\Album\Controller\Albumcontroller.php
<?php
namespace Album\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
class AlbumController extends AbstractActionController
{
protected $albumTable;
public function getAlbumTable()
{
if (!$this->albumTable) {
$sm = $this->getServiceLocator();
$this->albumTable = $sm->get('Album\Model\AlbumTable');
}
return $this->albumTable;
}
public function indexAction()
{
return new ViewModel(array(
'albums' => $this->getAlbumTable()->fetchAll(),
));
}
public function addAction()
{
}
public function editAction()
{
}
public function deleteAction()
{
}
}
My configuration:
Windows xp.
Zend Server CE Technology Preview (PHP 5.3).
Thank you for your help
Related
I have a Service Layer for my A module. Now I want to reuse the Service Layer by calling it from another module B. I understand that I have to inject my Service Layer in Controller of Module B.
My question is how do I give the path of the Service Layer for module B?
In my Controller Factory for module B, $serviceLocator->get('A\Service\AService'), and in my Controller, use A\Service\AService; these won't work as these are directory locations for module A.Also, It seems like default path starts from folder outside controllers. How do I use these path for B?
class IndexController extends AbstractActionController
{
function __construct(AService $sm) {
$this->sm =$sm;
}
public function indexAction()
{
$event = $this->getEvent();
$request = $event->getRequest();
$router = $event->getRouter();
$uri = $router->getRequestUri();
$baseUrl = sprintf('%s://%s%s', $uri->getScheme(), $uri->getHost(), $request->getBaseUrl());
$this->sm->callMethod($baseUrl);
}
}
My module.config.php,
return array(
'controllers' => array(
'factories' => array(
'Application\Controller\IndexController' => 'Application\Controller\IndexControllerFactory',
),
),
'router' => array(
'routes' => array(
'home' => array(
'type' => 'Zend\Mvc\Router\Http\Literal',
'options' => array(
'route' => '/',
'defaults' => array(
'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' => '/application',
'defaults' => array(
'__NAMESPACE__' => 'Application\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(
'abstract_factories' => array(
'Zend\Cache\Service\StorageCacheAbstractServiceFactory',
'Zend\Log\LoggerAbstractServiceFactory',
),
'aliases' => array(
'translator' => 'MvcTranslator',
),
),
'translator' => array(
'locale' => 'en_US',
'translation_file_patterns' => array(
array(
'type' => 'gettext',
'base_dir' => __DIR__ . '/../language',
'pattern' => '%s.mo',
),
),
),
'controllers' => array(
'invokables' => array(
'Application\Controller\Index' => 'Application\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/layout' => __DIR__ . '/../view/layout/layout.phtml',
'application/index/index' => __DIR__ . '/../view/application/index/index.phtml',
'error/404' => __DIR__ . '/../view/error/404.phtml',
'error/index' => __DIR__ . '/../view/error/index.phtml',
),
'template_path_stack' => array(
__DIR__ . '/../view',
),
),
// Placeholder for console routes
'console' => array(
'router' => array(
'routes' => array(
),
),
),
);
In module.php
public function getControllerConfig()
{
return array(
'factories' => array(
'Application\Controller\Index' => function ($sm){
$a = $sm->getServiceLocator()->get('A\Service\AService');
return new Application\IndexController($a);
}
),
);
}
It should works the same as using the Service in A controller.
I assume that you register service in module A
...
'invokables' => array(
'A\Service\AService' => 'A\Service\AService',
)
...
From that point you can use it in any module (eg. in your B modul Module.php):
public function getControllerConfig()
{
return array(
'factories' => array(
'B\Controller\Index' => function ($sm){
$a = $sm->getServiceLocator()->get('A\Service\AService');
return new B\IndexController($a);
}
),
);
}
I've got a problem with adding many controllers in the one module. Zend2 is difficult for beginners.
I've created Module "Home" with Controllers "Home" and "News". HomeController is going fine but when I'm trying to connect to the NewsController I'm getting Fatal error: Class 'Home\Controller\NewsController' not found in C:\wamp\www\zend2\vendor\zendframework\zendframework\library\Zend\ServiceManager\AbstractPluginManager.php on line 170. And I don't know where the problem is.
My module.config looks like
return array(
'controllers' => array(
'invokables' => array(
'Home\Controller\Home' => 'Home\Controller\HomeController',
'Home\Controller\News' => 'Home\Controller\NewsController',
),
),
'router' => array(
'routes' => array(
'home' => array(
'type' => 'segment',
'options' => array(
'route' => '/home[/][:action]',
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]*'
),
'defaults' => array(
'controller' => 'Home\Controller\Home',
'action' => 'index',
),
),
),
'news' => array(
'type' => 'segment',
'options' => array(
'route' => '/news[/][:action]',
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]*'
),
'defaults' => array(
'controller' => 'Home\Controller\News',
'action' => 'index',
),
),
),
),
),
'view_manager' => array(
'template_path_stack' => array(
'album' => __DIR__ . '/../view',
),
),
);
I'm using navigation factory so navigation file looks like :
return array(
'navigation' => array(
'default' => array(
array(
'label' => 'Home',
'route' => 'home'
),
array(
'label' => 'News',
'route' => 'news'
),
),
),
'service_manager' => array(
'factories' => array(
'navigation' => 'Zend\Navigation\Service\DefaultNavigationFactory'
)
)
);
And Module.php looks like
namespace Home;
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';
}
}
And NewsController looks like
namespace News\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
class NewsController extends AbstractActionController {
public function indexAction()
{
return array();
}
}
In your controller class you're declaring the namespace as:
namespace News\Controller;
yet in your module config you list the invokable class as Home\Controller\NewsController. The namespaces need to match, so you probably want to change the controller class namespace to:
namespace Home\Controller;
I am attempting to create multiple navigation menus to use in my application based on a specific user role. The majority of the code is similar to zfc-admin. When I use zfc-admin in my application I am able to bring up an admin menu, however I will have about four roles, and decided to put this in my Application module.
module.config.php
'navigation' => array(
'admin' => array(
array(
'label' => 'Admin Home',
'route' => 'adminhome',
),
),
'default' => array(
array(
'label' => 'Home',
'route' => 'home',
),
),
),
AdminNavigationFactory.php
namespace Application\Navigation\Service;
use Zend\Navigation\Service\DefaultNavigationFactory;
class AdminNavigationFactory extends DefaultNavigationFactory
{
protected function getName()
{
return 'admin';
}
}
Module.php
public function getServiceConfig()
{
return array(
'factories' => array(
'admin_navigation' => 'Application\Navigation\Service\AdminNavigationFactory',
),
);
}
layout.phtml
<?php echo $this->navigation('admin_navigation')->menu(); ?>
I get the error.
Fatal error: Uncaught exception 'Zend\ServiceManager\Exception\ServiceNotCreatedException' with message 'While attempting to create adminnavigation(alias: admin_navigation) an invalid factory was registered for this instance type.' in /Applications/MAMP/htdocs/myapp/vendor/zendframework/zendframework/library/Zend/ServiceManager/ServiceManager.php on line 987
If I change the layout.phtml to use the default menu everything works as expected.
<?php echo $this->navigation('navigation')->menu(); ?>
first I got exactly the same issue. After moving the factory configuration from the getServiceConfig() method in the module class to the module.config.php it worked.
So my admin navigation works now like the follows:
module.config.php
(module/Admin/config/module.config.php)
return array(
// yada yada yada...
'service_manager' => array(
'factories' => array(
'navigation' => 'Zend\Navigation\Service\DefaultNavigationFactory',
'adminnav' => 'Application\Navigation\Service\AdminNavigationFactory',
),
),
'navigation' => array(
'default' => array(
array(
'label' => 'Home',
'route' => 'home',
),
array(
'label' => 'Filme',
'route' => 'movies',
),
array(
'label' => 'Admin',
'route' => 'admin',
),
),
'adminnav' => array(
array(
'label' => 'Film hinzufügen',
'route' => 'add-movie',
),
array(
'label' => 'Buch hinzufügen',
'route' => 'add-book',
),
),
),
);
AdminNavigationFactory
(module/Application/src/Application/Navigation/Service/AdminNavigationFactory.php)
namespace Application\Navigation\Service;
use Zend\Navigation\Service\DefaultNavigationFactory;
class AdminNavigationFactory extends DefaultNavigationFactory
{
protected function getName()
{
return 'adminnav';
}
}
Maybe you want to check out the code in context of the entire application, so here are the links to the my github:
AdminNavigationFactory
module.config.php
Regards,
Sascha
I've been searching and trying for a while now and I can't find out what I'm doing wrong...
I've been reading quite some documentation now and have tried a lot of different approaches.
I hope one of you guys can help me out..
My idea:
I have a module called Application. In this module there is an \Application\Controller\IndexController which is used to show the homepage of my application.
The IndexController needs an object with \Zend\http\Client, so I though I should use the factories key in the configuration that is returned by \Application\Module->getServiceConfig() and add a constructor with required param \Zend\Http\Client $client.
Unfortunatly this is not working..
My code:
<?php
// module/Application/Module.php
namespace Application;
use Zend\Mvc\ModuleRouteListener;
use Zend\Mvc\MvcEvent;
class Module
{
public function getConfig()
{
return include __DIR__ . '/config/module.config.php';
}
public function getServiceConfig()
{
return array(
'factories' => array(
'IndexController' => function($serviceManager) {
$httpClient = \Zend\Http\Client;
return new IndexController($httpClient);
},
),
);
}
public function getAutoloaderConfig()
{
return array(
'Zend\Loader\StandardAutoloader' => array(
'namespaces' => array(
__NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__,
),
),
);
}
}
<?php
// module/Application/config/module.config.php
return array(
'router' => array(
'routes' => array(
'home' => array(
'type' => 'Zend\Mvc\Router\Http\Literal',
'options' => array(
'route' => '/',
'defaults' => array(
'controller' => 'Application\Controller\Index',
'action' => 'index',
),
),
)
),
),
'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(
'Application\Controller\Index' => 'Application\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/layout' => __DIR__ . '/../view/layout/layout.phtml',
'application/index/index' => __DIR__ . '/../view/index/index.phtml',
'error/404' => __DIR__ . '/../view/error/404.phtml',
'error/index' => __DIR__ . '/../view/error/index.phtml',
),
'template_path_stack' => array(
__DIR__ . '/../view',
),
),
);
<?php
// module/Application/src/Application/Controller/IndexController.php
namespace Application\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
class IndexController extends AbstractActionController
{
protected $httpClient;
public function __construct(\Zend\Http\Client $client)
{
$this->httpClient = $client;
}
public function getHttpClient()
{
return $this->httpClient;
}
public function indexAction()
{
$httpClient = $this->getHttpClient();
return new ViewModel();
}
}
The error:
Catchable fatal error: Argument 1 passed to Application\Controller\IndexController::__construct() must be an instance of Zend\Http\Client, none given, called in /var/www/library/Zend/ServiceManager/AbstractPluginManager.php on line 170 and defined in /var/www/module/Application/src/Application/Controller/IndexController.php on line 13
You need to implement the getControllerConfig method in Module.php to do what you're asking, controllers have their own manager, remove what you have from getServiceConfig, and use the following instead
public function getControllerConfig()
{
return array(
'factories' => array(
'Application\Controller\Index' => function($serviceManager) {
$httpClient = new \Zend\Http\Client;
return new \Application\Controller\IndexController($httpClient);
},
),
);
}
You'll also need to remove the line from controller invokables in module.config.php since it'll conflict with your factory
'controllers' => array(
'invokables' => array(
// this line's no longer needed
//'Application\Controller\Index' => 'Application\Controller\IndexController',
),
),
Is it possible to have 2 differents navigation ?
For example :
//in module.config.php
'service_manager'=>array(
'factories'=>array(
'navigation1'=>'Zend\Navigation\Service\DefaultNavigationFactory',
'navigation2'=>'Zend\Navigation\Service\DefaultNavigationFactory',
),
),
'navigation'=>array(
'navigation1'=>array(
'home'=>array('type' => 'mvc','route' => 'home','active'=>false,'label' => 'Home','title' => 'Home',
'pages'=>array(
'contact'=>array('type' => 'mvc','route'=>'contact','active'=>false,'label'=>'Contact','title' =>'Contact'),
)
),
),
'navigation2'=>array(
'home'=>array('type'=>'mvc','route'=>'home','active'=>false,'label'=>'Home','title'=>'Home',
'contact'=>array('type'=>'mvc','route'=>'faq','active'=>false,'label'=>'Faq','title'=>'Faq'),
),
),
//Dans laout
<?php echo $this->navigation()->menu('navigation1')->setMinDepth(0);?>
<hr />
<?php echo $this->navigation()->menu('navigation2')->setMinDepth(0);?>
I would like 2 differents menu with differents pages but this method doesn't run.
Every one has an idea please ?
Thanks
Birzat
You need to provide a custom factory class for each navigation group. For example, see how ZfcAdmin does this:
Create a custom factory class
<?php
namespace ZfcAdmin\Navigation\Service;
use Zend\Navigation\Service\DefaultNavigationFactory;
class AdminNavigationFactory extends DefaultNavigationFactory
{
protected function getName()
{
return 'admin';
}
}
Source: https://github.com/ZF-Commons/ZfcAdmin/blob/master/src/ZfcAdmin/Navigation/Service/AdminNavigationFactory.php
Register AdminNavigationFactory
// in Module.php
public function getServiceConfig()
{
return array(
'factories' => array(
'admin_navigation' => 'ZfcAdmin\Navigation\Service\AdminNavigationFactory',
),
);
}
Source: https://github.com/ZF-Commons/ZfcAdmin/blob/master/Module.php#L90
Define Navigation trees in your module's configuration under the key you specified in the getName method of your factory. As an example, this is how ZfcUserAdmin adds itself to the ZfcAdmin menu:
'navigation' => array(
'admin' => array(
'zfcuseradmin' => array(
'label' => 'Users',
'route' => 'zfcadmin/zfcuseradmin/list',
'pages' => array(
'create' => array(
'label' => 'New User',
'route' => 'admin/create',
),
),
),
),
),
Source: https://github.com/Danielss89/ZfcUserAdmin/blob/master/config/module.config.php
/vendor/MyNamespace/library/MyNamespace/Navigation/Service/SecondaryNavigationFactory.php
namespace MyNamespace\Navigation\Service;
use Zend\Navigation\Service\DefaultNavigationFactory;
class SecondaryNavigationFactory extends DefaultNavigationFactory {
protected function getName() {
return 'secondary';
}
}
/config/autoload/global.php
return array(
'service_manager' => array(
'factories' => array(
'navigation' => 'Zend\Navigation\Service\DefaultNavigationFactory',
'secondary' => 'MyNamespace\Navigation\Service\SecondaryNavigationFactory',
),
),
'navigation' => array(
'default' => array(
array(
'label' => 'Item-1.1',
'route' => 'foo',
),
array(
'label' => 'Item-1.2',
'route' => 'bar',
),
),
'secondary' => array(
array(
'label' => 'Item-2',
'route' => 'baz',
),
),
),
);
/module/Application/view/layout/layout.phtml
<?php echo $this->navigation('navigation')->menu(); ?>
<?php echo $this->navigation('secondary')->menu(); ?>