Reputation: 2796
I'm working on a Zend Framework (1.11) application that I am porting into modules so that the devs can plug and play various additions to our software and remove just as easily.
The issue I'm having (and don't seem to be able to find an answer for is) I have dependable library code, i.e my structure is currently this
- application
- (the standard ZF stuff)
- modules
- testModule
- Bootstrap.php
- controllers
- configs
- views
- library
- CoreStuff
- Class.php
- SpecialClass.php
- testModuleLibrary
- Class.php
- SpecialClass.php
And what I really want is this so that it is easier for the other devs to install modules to our system.
- application
- (the standard ZF stuff)
- modules
- testModule
- Bootstrap.php
- controllers
- configs
- views
- library
- Class.php
- SpecialClass.php
- library
- CoreStuff
- Class.php
- SpecialClass.php
Can I use the Autoloader in the module Bootstrap? or do I have to add it to my include path?
[EDIT]
This is my current module bootstrap, I've seen this code time and time again with my perilous Googling but it doesn't appear to make any difference
<?php
class Notifications_Bootstrap extends Zend_Application_Module_Bootstrap {
protected function _initLibraryAutoloader () {
return $this->getResourceLoader()->addResourceType('library', 'library', 'library');
}
}
Upvotes: 2
Views: 967
Reputation: 2283
I'm adding this response to hopefully both answer the original inquiry, as well as provide some clarification on a few items submitted here. I'm an active developer of modules in ZF 1.11, and use what I'm about to explain everyday in one of the several modules we maintain.
My apologies ahead of time for the length of this response. There are several items to cover and consider.
First, for the implementation.
The following snippet that was provided as far as I know worked ~1.8, and would not be what you want for 1.11.
<?php
class Notifications_Bootstrap extends Zend_Application_Module_Bootstrap {
protected function _initLibraryAutoloader () {
return $this->getResourceLoader()->addResourceType('library', 'library', 'library');
}
}
The following though would work fine provided a few key elements I'll explain below.
protected function _initLibraryAutoloader () {
return $this->getResourceLoader()->addResourceType('library', 'library', 'Library_');
}
You'll notice a slight difference in the third parameter ( the namespace ). The best explanation of this would be to possibly update the function to the following:
protected function _initLibraryAutoloader () {
$this->getResourceLoader()->addResourceType('library', 'library', 'Library_');
var_dump($this->getResourceLoader()->getResourceTypes());die;
}
Your output should be something similar to:
Array
(
[dbtable] => Array
(
[namespace] => Admin_Model_DbTable
[path] => /path/to/trunk/application/modules/admin/models/DbTable
)
[mappers] => Array
(
[namespace] => Admin_Model_Mapper
[path] => /path/to/trunk/application/modules/admin/models/mappers
)
[form] => Array
(
[namespace] => Admin_Form
[path] => /path/to/trunk/application/modules/admin/forms
)
[model] => Array
(
[namespace] => Admin_Model
[path] => /path/to/trunk/application/modules/admin/models
)
[plugin] => Array
(
[namespace] => Admin_Plugin
[path] => /path/to/trunk/application/modules/admin/plugins
)
[service] => Array
(
[namespace] => Admin_Service
[path] => /path/to/trunk/application/modules/admin/services
)
[viewhelper] => Array
(
[namespace] => Admin_View_Helper
[path] => /path/to/trunk/application/modules/admin/views/helpers
)
[viewfilter] => Array
(
[namespace] => Admin_View_Filter
[path] => /path/to/trunk/application/modules/admin/views/filters
)
[library] => Array
(
[namespace] => Admin_Library
[path] => /path/to/trunk/application/modules/admin/library
)
)
If you compare this to your previous "library" as the third parameter, you'll see in a second why it makes such an important difference.
To reiterate, at this point, you've declared a library type with the prefix of "Library_", which is translating to "Admin_Library". Now, to implement this, you'll have your library folder in your module just as you do in your main application module, with one slight adjustment. To have an Admin module specific controller action ( Admin_Library_Controller_Action ), you'll have library/Controller/Action.php, with a class name of Admin_Library_Controller_Action. This is what most find confusing at first, but it's very similar to the other resource namespaces you should be using in modules.
That concludes the technical explanation. If you read no further, you'll be able to have a library specific to your module and totally self-contained for easy copy/paste implementation of a reusable module.
Now for a few comments about some of the other responses I saw here.
infinity noted
"If you follow your structure you might end up with - Module1 (Lib1, Lib2) - Module2 (Lib1, Lib3) so you'll start duplicating the needed libraries."
This is technically correct, but really brings to light more issues in your actual development style if you find yourself routinely using the same libraries all over the place. We generally store these common items in another library, that we use as an external, identical to Zend, and is placed along side Zend in the main application library folder.
Provided you're already doing that, Where I believe some additional clarification might be needed is, if you're using the namespaces correctly, you absolutely don't have to worry about a collision of library class names. You may for a short period of time find that you need to have classes with identical code in multiple modules, but as soon as this happens, you should consider the common library in addition to Zend that I mentioned above.
My apologies again for the length of this response. I hope that it helps anyone who might come across this post in need of library implementation in modules.
Upvotes: 0
Reputation: 10015
You can define your library paths in the application config file like: This is example in YML
project:
bootstrap:
path: APPLICATION_PATH/Bootstrap/index.php
class: Bootstrap_Index
Autoloadernamespaces:
- Zend_
- Library1_
- Library2_
resources:
FrontController:
moduledirectory:
- APPLICATION_PATH/modules
......
Here is example in INI format
[bootstrap]
Autoloadernamespaces[] = "Zend_"
Autoloadernamespaces[] = "Library1_"
Autoloadernamespaces[] = "Library2_"
resources.FrontController.moduleDirectory = APPLICATION_PATH"/modules"
resources.FrontController.resetRouterOnEveryRequest = true
bootstrap.path = APPLICATION_PATH "/Bootstrap/index.php"
bootstrap.class = "Bootstrap_Index"
Regarding the project directory structure I advise you to use something similar to:
- application
- Bootstrap
- index.php
- Modules
- Mod1
- controllers
- views
- Mod2
- controllers
- views
...
- library
- Zend
- ...
- Library1
- ...
- Library2
- ...
Having done the directory structure you can have URLs like /:module/:controller/:action and keep all 3rd party code separate in its own pool Library directory
Upvotes: 1
Reputation: 2796
I have resolved my issue with the following code. I literally have no idea why I didn't come up with this earlier :( :(
class Notifications_Bootstrap extends Zend_Application_Module_Bootstrap {
protected function _initConfig () {
set_include_path(implode(PATH_SEPARATOR, array(
dirname(__FILE__) . '/library',
get_include_path(),
)));
}
}
Upvotes: 1
Reputation: 2760
You may just use the modules' Boostrap.php. Provide a function
protected function _initAutoload(){}
to make the lib available. Thus you may just make the module-developer do it, as it is part of the work developing a module to make it's resources loadable :)
Upvotes: 0