Reading the section Zend_Application_Resource_Modules in the docs here:
http://framework.zend.com/manual/1.10/en/zend.application.available-resources.html
I noticed this:
You can specify module-specific configuration using the module name as a prefix or sub-section in your configuration file.
using this:
[production]
news.resources.db.adapter = "pdo_mysql"
news.resources.db.params.host = "localhost"
news.resources.db.params.username = "webuser"
news.resources.db.params.password = "XXXXXXX"
news.resources.db.params.dbname = "news"
To me this is a good idea. But, when I simply add these prefixes to certain things I want to be specific to my modules, nothing changes.
So my question is: How do I tell Zend Framework to actually use these module specific prefixes?
I use the following implementation of modules in Zend. It allows you to use "module-specific" configuration.
application/config/config.ini
-----------------------------
[production]
resources.modules[] =
By doing this, you're telling Zend_Application that you want to use the Modules Bootstrap Resource plugin. The Modules plugin will load a separate bootsrap class for each of your modules, excluding the default module. Therefore, you need to create a new bootstrap class for your second module.
application/modules/news/Bootstrap.php
-----------------------------
class News_Bootstrap extends Zend_Application_Module_Bootstrap {
//---------------------------------------
// Automatically load our resources
//
// NOTE: You don't have to add this, its
// just and example to show that you
// can customize the bootstrap
// process just for this module.
public function _initModuleResourceAutoloader(){
$this->getResourceLoader()->addResourceTypes(array(
'modelResource' => array(
'path' => 'models/resources',
'namespace' => 'Resource'
)
));
}
}
This "News_Bootstrap" class will now be loaded and executed during the bootstrap process.
The naming convention for this file is important as the Modules Resource plugin needs to be able to find the class. Note that you must name the file Bootstrap.php.
Finally, you'll notice that you're subclassing the Zend_Application_Module_Bootstrap rather than Zend_Application_Bootstrap_Bootstrap like you do in the main bootstrap.
Now, your module-specific configuration should work:
[production]
news.resources.db.adapter = "pdo_mysql"
news.resources.db.params.host = "localhost"
news.resources.db.params.username = "webuser"
news.resources.db.params.password = "XXXXXXX"
news.resources.db.params.dbname = "news"
Related
I don't have a custom Zend_Form and I just declared all the elements in the ini file. There is no problem with creating the Zend_Form from the ini file, but I am having problem using my own custom validator in my ini file. It always return Not Found In Registry error.
Currently, my code is like this.
[Bootstrap]
$resourceLoader = new Zend_Loader_Autoloader_Resource(array(
'namespace' => 'MY',
'basePath' => dirname(__FILE__)
));
$resourceLoader->addResourceType('validator', 'forms/validate/', 'Form_Validate');
[ini file]
form.elements.new_password.options.validators.password.validator = "Password"
[Custom Validator]
<?php
class MY_Form_Validate_Password extends Zend_Validate_Abstract
{
......
Please tell me what I'm missing here. Thanks!
This is a case of over thinking:
I'm going to assume you're using a version of ZF1.x that's fairly new (v1.10 and newer).
You have a file called project/application/configs/application.ini
in a standard application.ini is the line:
includePaths.library = APPLICATION_PATH "/../library"
this tells us that all of our library code (a custom validator qualifies) would belong to the directory at this path.
Also there is the line:
autoloaderNamespaces[] = "MY_"
This tells us the name of our library (defines the directory below /library).
so our custom validator MY_Form_Validate_Password would live at:
project
/library
/MY
/Form
/Validate
Password.php
nothing else is required, all that bootstrap code is only needed if you are going to do something not anticipated by Zend Framework, also validators are not typically registered as resources.
The class can be called as
$validator = new MY_Form_Validate_Password();
as usual and any other access method should work as well.
I'm trying to learn Zend Framework! I'm quite interested in it but I can't find a tutorial which says where it's suppoused to be a Zend_Form class stored! Maybe it's something quite straightforward but I can't get it yet...
I've seen tutorials about this:
<?php
class Form_Example extends Zend_Form
{
public function init()
{
// Great code here
}
}
But none of them said where this code goes????? In a file in which folder in the directory tree?? I've read and I understand and I've done a little example with modules, controllers, actions, layouts and I know the importance about name conventions and the folder structure. So where does this form class must go and how can I call it from a view??
Thanks a lot, I know this must be easy for someone who already knows how to work well with Zend Framework =)
The best way to do this is to let ZF do it for you. ZF ships with a command line interface for both windows and *nix.
At the command line you can type zf create form Example, ZF will then create an empty form named Example.php at it's default application level location.
Typically this will be at application/forms/Example.php and the classname will be Application_Form_Example.
If you need to have a form constructed in a module the command would be similar:
zf create form Example -m admin where -m indicates you want the file created in a module and admin is name of the module.
Forms are one of the predefined resources in Zend Framework and as such have a default location. There are several other resources that are predefined and have defaults.
The Module Resource Autoloader
Zend Framework ships with a concrete implementation of
Zend_Loader_Autoloader_Resource that contains resource type mappings
that cover the default recommended directory structure for Zend
Framework MVC applications. This loader,
Zend_Application_Module_Autoloader, comes with the following mappings:
forms/ => Form
models/ => Model
models/DbTable/ => Model_DbTable
models/mappers/ => Model_Mapper
plugins/ => Plugin
services/ => Service views/
helpers => View_Helper
filters => View_Filter
As an example, if you have a module with the prefix of "Blog_", and attempted to instantiate the class
"Blog_Form_Entry", it would look in the resource directory's "forms/"
subdirectory for a file named "Entry.php". When using module
bootstraps with Zend_Application, an instance of
Zend_Application_Module_Autoloader will be created by default for each
discrete module, allowing you to autoload module resources.
I normally have all my forms in a forms folder, alongside the models, controllers, and views.
So, my file structure looks like:
application ->
configs
layouts
plugins
controllers
models
views
forms ->
form1.php
form2.php
Using them in your application isn't quite so simple. You must instantiate the form class in your controller, then pass the form to your view. So in your controller you want something like:
$form1 = new Application_Form_Form1($options);
$request = $this->getRequest();
if($request->isPost()) {
if($form1->isValid($post)) {
// form is valid, do form processing here
}
}
$this->view->form1 = $form1;
Then inside of your view file, you place the form:
<html>
<body>
<div id="body">
<?php echo $this->form1; ?>
</div>
</body>
</html>
At the heart of your question are the issues of:
autoloading
how the ZF autoloader works in general, and
how the ZF autoloader is configured by default in a standard ZF app
which are actually three distinct, though clearly-related, issues.
Assuming that you have the default ZF installation in which the appnamespace is set to "Application", then name your form class Application_Form_Example and store it in the file application/forms/Example.php.
Then you can instantiate (in a controller, for example) using:
$form = new Application_Form_Example().
Make sure that you have resources.modules[] = in application/configs/application.ini.
For additional discussion about autoloading, see https://stackoverflow.com/a/10933376/131824
I'm getting
Fatal error: Class 'Form_Login' not found in /route/to/project/application/controllers/AuthController.php on line XX
when instantiating the class From_Login inside the controller.
I suppose the form is not being autoloaded by the bootstrap class.
In my bootstrap file I have this method
protected function _initAutoload(){
$modelLoader = new Zend_Application_Module_Autoloader(array(
'namespace' => '',
'basePath' => APPLICATION_PATH));
return $modelLoader;
}
supposed to autoload my resources.
I'm using the default project structure.
-application
--controllers
---Authcontroller.php
--forms
---Login.php
when I created the form with zf tool it automatically set the name as Application_Form_Login then I erased the Application_ part since I'm using "" namespace. I doesn't work either way.
I've also tried setting appnamespace="" in the application.ini file but nothing happened
After trying over and over different options I got tired because it didn't work so I erased the project folder and started from the beginning whit zend tool and ... voilĂ , it works!
In my opinion it was a problem with zend tool and/or the .zfproject.xml file since I was adding some resources manually and some others with the zf tool.
use Zend modular structure and change your class name 'Form_Login' to 'Default_Form_Login' .
I would like to keep the old default Zend Router, and just add a router for administration subpages since the controllers are growing in size and I would like to logically separate them a little as well as have cleaner URLs.
The documentation seems to explain how to do other things but not this...
This will work out of the box with the default routes. You just need to add an administration module, and then /administration/users will map to the users controller in the administration module.
I don't know if its possibile to do it with an Underscore and the upcase user, sorry, but without you had to add the following to your bootstrap.php
$ctrl = Zend_Controller_Front::getInstance();
$router = $ctrl->getRouter();
$route['admin_users'] = new Zend_Controller_Router_Route_Regex(
'administration/users',
array(
'controller' => 'administrationusers',
)
);
$router->addRoute('admin_users_route', $route['admin_users']);
note: in this scenario your controller is:
class AdministrationusersController extends Zend_Controller_Action
{
// stuff
}
Does anyone know of a way to set the default module dynamically in Zend Framework and not run into namespace issues? For example, what I want to do is have a table of modules that are allowed to be loaded, with one of them set as the default module. For example, I may have:
admin
blog
calendar
as modules that can be loaded. If I have 'blog' as the default module, then 'admin' and 'calendar' have to have their controllers namespaced (Admin_IndexController, Calendar_IndexController) while 'blog' isn't (IndexController).
If I change 'calendar' to be the default module, ZF can no longer find the classes because of the namespacing.
How do you get around that? I'm currently using the following code:
$modules = new Modules();
$activeModules = $modules->fetchActive();
foreach($activeModules as $mod) {
$loadedModules[$mod->name] = '..application/modules/' . $mod->name . '/controllers';
if($mod->default) {
$defaultModule = $mod->name;
}
}
$frontController->setControllerDirectory($loadedModules);
$frontController->setDefaultModule($defaultModule);
If you plan on changing the default module, it is probably best to namespace ALL modules, and then specify that the default module should be prefixed:
First change the "blog" module to use namespacing:
<?php
// Used to be "class IndexController"
class Blog_IndexController extends Zend_Controller_Action {
}
Then, call setParam for prefixDefaultModule option on your instance of Zend_Controller_Front:
<?php
// Allow your default module to be prefixed
$frontController->setParam('prefixDefaultModule', true);
See bug # 1831 for an explanation.
use application.ini:
resources.frontController.prefixDefaultModule = true
resources.frontController.defaultModule = default
You can make a default module actually be the deciding part in this whole process.
More specifically - make all requests for default module go to a class that then will decide what specific module is currently default one and will re-route request to it.
At least that's the way we've implemented it ;)
Sounds like the work of a preDispatch Controller Plugin.
You can modify the request to change a module based on certain request or identity/session/known data to forward or redirect on demand.