How to load namespace for all modules (global autoload for whole application)
So far I need to add this to each module:
public function getAutoloaderConfig()
{
return array(
/* ... */
'Zend\Loader\StandardAutoloader' => array(
'namespaces' => array(
/* ... */
'MyNameSpace' => __DIR__ . '/../../library/MyNameSpace',
),
),
);
}
how can I implement this functionality in application.config.php? (i just want to load some base classes for whole application)
To load the modules you need use the file /config/application.config.php
Add the list of your modules to the array under module key.
return array(
// This should be an array of module namespaces used in the application.
'modules' => array(
'Application',
'Pages',
'ModuleName',
),
// ..... rest of array
)
The function getAutoloaderConfig() and getConfig() are used to load the configuration of the module (module internal configuration).
http://framework.zend.com/manual/2.0/en/user-guide/modules.html
autoload that path in your index.php, i.e.,
set_include_path(get_include_path() . PATH_SEPARATOR . __DIR__ . '/../../library/MyNameSpace');
spl_autoload_register(function ($class) {
if(!class_exists($class)) {
$class = str_replace('\\', '/', $class) . '.php';
require_once($class);
}
});
I don't think that you can (or should) do this in the application.config.php file. The whole point behind modules in the ZF2 framework is to separate logic into reusable, independent bits of code. As such, each module maintains and manages its own configuration, including autoloading, independent of the main application or other modules. These settings can often be overridden with the .global.php and .local.php files of the main autoload/ directory, but the autoloading should be left to each individual module.
If the modules you're trying to include are custom pieces of code that you have developed, then perhaps you might want to look at whether they are actually modules at all, or simply code that belongs in the Application module.
Related
PHP-DI 6 provides multiple functions, that working in the definitions. Three of them seem to do the same in the definitions context: autowire(...), create(...), and get(...). E.g. I have following types:
FooServiceInterface
BarServiceInterface
FooAService implements FooServiceInterface
dependencies: BarServiceInterface $barService
FooBService implements FooServiceInterface
dependencies: BarServiceInterface $barService
BarService implements BarServiceInterface
dependencies: -
The FooServiceInterface gets injected into a Symfony controller (constructor injection).
Now my file with the definitions:
return [
FooServiceInterface::class => DI\autowire(FooBService::class),
BarServiceInterface::class => DI\autowire(BarService::class),
];
It works.
I also can set it up like this:
return [
FooServiceInterface::class => DI\get(FooBService::class),
BarServiceInterface::class => DI\get(BarService::class),
];
And it's still working.
This
return [
FooServiceInterface::class => DI\create(FooBService::class),
BarServiceInterface::class => DI\create(BarService::class),
];
doesn't work.
And this
return [
FooServiceInterface::class => DI\get(FooBService::class),
BarServiceInterface::class => DI\create(BarService::class),
];
does.
What is the difference between the three functions (in the context of definitions)? Which one is the recommended function to set up a common interface dependency definition (like SomeInterface::class => DI\recommendedFunction(SomeClass::class))?
I would say use get() only if you know why you would need it.
Then to choose between autowire() and create() is up to you: do you need autowiring or not?
Using simply create() is telling PHP-DI to just do new FooService() to create the service. If that's enough, then fine. If your service has dependencies, you can either rely on autowiring (using autowire()) or define the dependencies to inject manually using create(). It's up to you.
C:\Program Files (x86)\Zend\Apache2\htdocs\zf2-tutorial\public\index.php:
<?php
/**
* This makes our life easier when dealing with paths. Everything is relative
* to the application root now.
*/
chdir(dirname(__DIR__));
// Decline static file requests back to the PHP built-in webserver
if (php_sapi_name() === 'cli-server' && is_file(__DIR__ . parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH))) {
return false;
}
// Setup autoloading
require 'init_autoloader.php';
// Run the application!
Zend\Mvc\Application::init(require 'config/application.config.php')->run();
If I place a file in the same directory called console.php:
<?php
echo __DIR___
?>
and run:
php console.php
The output is:
C:\Program Files (x86)\Zend\Apache2\htdocs\zf2-tutorial\public
Clearly this seems to be the wrong directory as 'init_autoloader.php' is actually located here:
C:\Program Files (x86)\Zend\Apache2\htdocs\zf2-tutorial
Also my book says that the line:
Zend\Mvc\Application::init(require 'config/application.config.php')->run();
calls the bootstrap() method of the Zend\Mvc\Application. I'm not sure how a call to init() translates to a call to bootstrap() could someone please explain this to me?
My book also says that the call to init takes care of instantiating a new ServiceManager object although I'm not sure how because I see nothing in the bootstrap method of the Application model that has anything to do at all with ServiceManager. Could someone explain this to me?
Thank you for posting...
For reference zf2-tutorial/Module/Application/Module.php
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* #link http://github.com/zendframework/ZendSkeletonApplication for the canonical source repository
* #copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
* #license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Application;
use Zend\Mvc\ModuleRouteListener;
use Zend\Mvc\MvcEvent;
class Module
{
public function onBootstrap(MvcEvent $e)
{
$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__,
),
),
);
}
}
Clearly this seems to be the wrong directory as 'init_autoloader.php' is actually located here: C:\Program Files (x86)\Zend\Apache2\htdocs\zf2-tutorial
The output from your console.php is different because in index.php you'll see this line ...
chdir(dirname(__DIR__));
This effectiveley changes up one directory to C:\Program Files (x86)\Zend\Apache2\htdocs\zf2-tutorial which is the root of the application and the same folder in which init_autoloader.php is located.
Also my book says that the line: Zend\Mvc\Application::init(require 'config/application.config.php')->run(); calls the bootstrap() method of the Zend\Mvc\Application.
You are confusing the Zend\Mvc\Application with the skeleton application module named Application. They are not the same thing.
The bootstrapping being referred to by your book is happening here in the code ...
https://github.com/zendframework/zf2/blob/master/library/Zend/Mvc/Application.php#L247-L261
As you can see it's a static method, which instantiates the ServiceManager and proceeds to set up services before finally bootstrapping the application here ...
https://github.com/zendframework/zf2/blob/master/library/Zend/Mvc/Application.php#L136-L158
For further reading I'd suggest familiarizing yourself with the MVC layer by reading the docs here
http://framework.zend.com/manual/2.3/en/modules/zend.mvc.intro.html
Hello i am new to this framework and i am getting this error when following the tutorial.
Fatal error: Uncaught exception 'Zend\ModuleManager\Exception\RuntimeException' with message 'Module (Album) could not be initialized.' in C:\website\zend\vendor\ZF2\library\Zend\ModuleManager\ModuleManager.php on line 175
here is the code that i believe there is a mistake
<?php
return array(
// This should be an array of module namespaces used in the application.
'modules' => array(
'Application',
'Album', // <-- Add this line to make new module available
),
// These are various options for the listeners attached to the ModuleManager
'module_listener_options' => array(
// This should be an array of paths in which modules reside.
// If a string key is provided, the listener will consider that a module
// namespace, the value of that key the specific path to that module's
// Module class.
'module_paths' => array(
'./module',
'./vendor',
),
// An array of paths from which to glob configuration files after
// modules are loaded. These effectively override configuration
// provided by modules themselves. Paths may use GLOB_BRACE notation.
'config_glob_paths' => array(
'config/autoload/{,*.}{global,local}.php',
),
// Whether or not to enable a configuration cache.
// If enabled, the merged configuration will be cached and used in
// subsequent requests.
//'config_cache_enabled' => $booleanValue,
// The key used to create the configuration cache file name.
//'config_cache_key' => $stringKey,
// Whether or not to enable a module class map cache.
// If enabled, creates a module class map cache which will be used
// by in future requests, to reduce the autoloading process.
//'module_map_cache_enabled' => $booleanValue,
// The key used to create the class map cache file name.
//'module_map_cache_key' => $stringKey,
// The path in which to cache merged configuration.
//'cache_dir' => $stringPath,
// Whether or not to enable modules dependency checking.
// Enabled by default, prevents usage of modules that depend on other modules
// that weren't loaded.
// 'check_dependencies' => true,
),
// Used to create an own service manager. May contain one or more child arrays.
//'service_listener_options' => array(
// array(
// 'service_manager' => $stringServiceManagerName,
// 'config_key' => $stringConfigKey,
// 'interface' => $stringOptionalInterface,
// 'method' => $stringRequiredMethodName,
// ),
// )
// Initial configuration with which to seed the ServiceManager.
// Should be compatible with Zend\ServiceManager\Config.
// 'service_manager' => array(),
);
Like #foozy said, if you can post more of the code, that would be a big help. It could be a number of things, such as the name you've specified in module.config.php is different from the Module directory or namespace, or a variety of things.
I have an application with some modules. One of them is CourseSearch. Now I want to add a further one, the SportsPartnerSearch. Since these two modules are very similar to each other, I simply "cloned" / copied the CourseSearch and replaced all "Course" with "SportsPartner" (in all variations: $course to $sportsPartner, course-...phtml to sports-partner-...phtml etc.), in order to edit the logic in the second step. Now I'm getting following errors:
Warning:
require_once(/path/to/project/module/SportsPartnerSearch//src/CourseSearch/View/Helper/CourseSearchForm.php):
failed to open stream: No such file or directory in
/path/to/project/vendor/zendframework/zendframework/library/Zend/Loader/ClassMapAutoloader.php
on line 140
Fatal error: require_once(): Failed opening required
'/path/to/project/module/SportsPartnerSearch//src/CourseSearch/View/Helper/CourseSearchForm.php'
(include_path='.:/usr/share/php:/usr/share/pear') in
/path/to/project/vendor/zendframework/zendframework/library/Zend/Loader/ClassMapAutoloader.php
on line 140
Why is the path to the file being built in such strange way: /path/to/project/module/SportsPartnerSearch//src/CourseSearch/View/Helper/CourseSearchForm.php? Where did I do a mistake?
Some additional information.
The class, that cannot be found because the wron path is CourseSearch\View\Helper\CourseSearchForm in the CourseSearch module. It can be found, when I deactivate the new module SportsPartnerSearch, that contains the class SportsPartnerSearch\View\Helper\SportsPartnerSearchForm.
The CourseSearchForm view helper is instanciated in the CourseSearchForm\Module
class Module {
public function getViewHelperConfig() {
return array(
'factories' => array(
'courseSearchForm' => function($serviceManager) {
$helper = new View\Helper\CourseSearchForm(array('render' => true, 'redirect' => false));
// ERROR. This code is not executed anymore.
$helper->setViewTemplate('course-search/course-search/course-search-form');
$courseSearchForm = $serviceManager->getServiceLocator()->get('CourseSearch\Form\CourseSearchForm');
$helper->setCourseSearchForm($courseSearchForm);
return $helper;
}
)
);
}
}
And called in the layout file:
echo $this->courseSearchForm();
The SportsPartnerSearch\View\Helper\SportsPartnerSearchForm is instanciated in the same way in the SportsPartnerSearch\Module#getViewHelperConfig() and is not called yet.
Have you generated a classmap? Check the autoload_classmap.php file in both the CourseSearch and the SportsPartnerSearch modules. I guess you still have an old classmap lying around. I think the problem is hidden inside the classmap because of the error in the ClassMapAutoloader from Zend, and not the standard autoloader.
You can generate a new classmap with the classmap generator provided in ZF2 (assuming you load it via Composer) with:
cd module/SportsPartnerSearch
../../vendor/bin/classmap_generator.php
This will generate a new classmap file inside the SportsPartnerSearch module.
I am very new to Zend Framework 2 and am using the book “Web Development with Zend Framework 2” by Michael Romer as my guide. I’m at the end of chapter 5 and the subject of the ClassMapAutoloader is presented. The conclusion of the discussion is that my Helloworld module now has the file and directory structure of ->
Module.php
autoload_classmap.php
autoload_function.php
autoload_register.php
config/
module.config.php
public/
images/
css/
js/
src/
Helloworld/
Controller/
IndexController.php
views/
Helloworld/
Index/
index.phtml
As far as I can tell the files of interest that setup Classmap autoloading are Module.php, autoload_classmap.php, autoload_function.php, autoload_register.php. The contents of these files are
Module.php ->
<?php
namespace Helloworld;
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';
}
}
autoload_function.php ->
<?php
return function ($class) {
static $classmap = null;
if ($classmap === null) {
$classmap = include __DIR_ . '/autoload_classmap.php';
}
if (!isset($classmap[$class])) {
return false;
}
return include_once $classmap[$class];
};
autoload_register.php ->
<?php
spl_autoload_register(include __DIR__ . '/autoload_function.php');
autoload_classmap.php ->
<?php
//require_once 'autoload_register.php';
return array();
This all works when I have that blank array return in autoload_classmap.php BUT in the book the example has require_once 'autoload_register.php';. When I uncomment that line I get the following error ->
The error is -> [Tue Jun 18 16:29:20 2013] [error] [client 199.82.163.121] PHP Fatal error: Uncaught exception 'Zend\Loader\Exception\InvalidArgumentException' with message 'Map file provided does not return a map. Map file: "/var/www/ZendApp/module/Helloworld/autoload_classmap.php"' in /var/www/ZendApp/vendor/zendframework/zendframework/library/Zend/Loader/ClassMapAutoloader.php:88\nStack trace:\n#0 /var/www/ZendApp/vendor/zendframework/zendframework/library/Zend/Loader/ClassMapAutoloader.php(117): Zend\Loader\ClassMapAutoloader->registerAutoloadMap('/var/www/ZendAp...')\n#1 /var/www/ZendApp/vendor/zendframework/zendframework/library/Zend/Loader/ClassMapAutoloader.php(60): Zend\Loader\ClassMapAutoloader->registerAutoloadMaps(Array)\n#2 /var/www/ZendApp/vendor/zendframework/zendframework/library/Zend/Loader/ClassMapAutoloader.php(46): Zend\Loader\ClassMapAutoloader->setOptions(Array)\n#3 /var/www/ZendApp/vendor/zendframework/zendframework/library/Zend/Loader/AutoloaderFactory.php(100): Zend\Loader\ClassMapAutoloader->__construct(Array)\n#4 /var/www/ZendApp/vendor/zendframework/zendframework/library/Zend/M in /var/www/ZendApp/vendor/zendframework/zendframework/library/Zend/Loader/ClassMapAutoloader.php on line 88
I know that returning the blank array causes the getAutoloaderConfig() in the Module class of Module.php to default to the StandardAutoloader and thus it works but Why? I’d really like to get the ClassMapAutoloader to do its thing in this example. How do I get this to work? Thanks in advance for your reply.
James Eastman
There is no such thing as requiring the autoloader register function in the classmap file. That is not even in the books.
You can generate the autoloader classmap with the classmap generator provided within Zend Framework 2. You can generate the autoload_classmap.php file so it is populated with all the php classes in your module.
Usage:
$ cd module/MyModule
$ ../../vendor/zendframework/zendframework/bin/classmap_generator.php -w
This works in the case you loaded Zend Framework 2 with composer, which loads the library in the vendor/ directory.
in Module.php after name add the two lines of code!
namespace Helloworld;
use Zend\Mvc\ModuleRouteListener;
use Zend\Mvc\MvcEvent;