How to autoload extra module classess automatically like of default namespace "Application_"? - zend-framework

All the classes under a default namespace Application_ is autoloaded by default. When you are creating more modules, the classes under that module is not autoloaded.
I tried setting the extra module's namespace on the application.ini like
autoloaderNamespaces[] = "EXTRA_"
but since the folder structure of the extra modules lies inside the Application it cannot find it.
How to set this correctly?

You can use application resource modules
Module bootstrap(if subclass of Zend_Application_Module_Bootstrap) register autoloader on instantiation.
Following is array of resources registered with autoloader by default:
array(
'dbtable' => array(
'namespace' => 'Model_DbTable',
'path' => 'models/DbTable',
),
'mappers' => array(
'namespace' => 'Model_Mapper',
'path' => 'models/mappers',
),
'form' => array(
'namespace' => 'Form',
'path' => 'forms',
),
'model' => array(
'namespace' => 'Model',
'path' => 'models',
),
'plugin' => array(
'namespace' => 'Plugin',
'path' => 'plugins',
),
'service' => array(
'namespace' => 'Service',
'path' => 'services',
),
'viewhelper' => array(
'namespace' => 'View_Helper',
'path' => 'views/helpers',
),
'viewfilter' => array(
'namespace' => 'View_Filter',
'path' => 'views/filters',
),
)
You can add your own module resource type to autoloader from module bootstrap:
//module bootstrap for module foo
class Foo_Bootstrap extends Zend_Application_Module_Bootstrap
{
function _initMyRes()
{
$autoloader = $this->getResourceLoader();
$autoloader->addResourceType('myres', 'myres/custom/path', 'My_Res');
}
}
first parameter is a key for resource type, second is a path relative to module name, third is a resource prefix.
For example class Foo_My_Res_Bar will be autoloaded from modules/foo/myres/custom/path/Bar.php

Namespaces is for your own library classes (like the Zend_) classes. Modules are different thing and don't have namespace in that sense.
In the application.ini configuration you will have something like this
autoloaderNamespaces.My = "My_"
// these are you library classes
resources.frontController.moduleDirectory = APPLICATION_LIBRARY "/modules"
// this is your module directory
UPDATE If you need support for more than one module directory you need ZF 1.11.1 or this bugfix

In the Bootstrap class for each module, create a new module resource autloloader:
protected function _initResourceAutoloader()
{
$resourceAutoloader = new Zend_Application_Module_Autoloader(array(
'namespace' => 'Mymodule',
'basePath' => dirname(__FILE__),
));
}
Then, you can use the "standard" folder structure for module-specific classes. For example, a form named Mymodule_Form_Edit would reside in the file modules/mymodule/forms/Edit.php
UPDATE
As noted by #Xerkus and others, a module Bootstrap extending Zend_Application_Module_Bootstrap will automatically register some standard namespace/path mappings, so no need to manually instantiate a Zend_Application_Module_Autoloader.

Related

Where and How to Locate this Zend Controller Plugin

I have a Zend front controller plugin. It depends on the request object, and on the service layer, but it is not reusable across applications. Therefore, I think it belongs in a Plugins directory within the application's controller directory. Does this sound right?
Secondly, how can I get Zend to autoload the plugins in this directory?
Thanks!
I would agree that plugins should go in the plugins folder. I normally setup an instance of the resource autoloader during bootstrap using my app's custom namespace. E.g. say your app's namespace was 'Bob':
protected function _initAutoloader()
{
$autoloader = Zend_Loader_Autoloader::getInstance();
$resourceAutoloader = new Zend_Loader_Autoloader_Resource(array(
'basePath' => APPLICATION_PATH,
'namespace' => 'Bob',
'resourceTypes' => array(
'model' => array(
'path' => 'models/',
'namespace' => 'Model'
),
'form' => array(
'path' => 'forms/',
'namespace' => 'Form'
),
'plugin' => array(
'path' => 'plugins/',
'namespace' => 'Plugin'
),
'service' => array(
'path' => 'services/',
'namespace' => 'Service'
)
)
));
$autoloader->pushAutoloader($resourceAutoloader);
return $autoloader;
}
Add or remove resource types as required. You can then put your plugin in application/plugins/Whatever.php and it will be autoloaded as normal.

Zend 2 router setting

Im very mew to ZF2, and cant figure out how to set the global router.
I know how to set on module level:
http://packages.zendframework.com/docs/latest/manual/en/user-guide/routing-and-controllers.html says:
The mapping of a URL to a particular action is done using routes that
are defined in the module’s module.config.php file. We will add a route
for our album actions. This is the updated config file with the new
code commented.
// The following section is new and should be added to your file
'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',
),
),
),
),
),
Is there a way to config a default behaviour for the whole application? Or i have to confing in each module?
config/application.config.php would be a logical place for it. Is it somewhere documented?
What your ZF2 module defines in getConfig() gets merged with all the other module configs and eventually replaced by modules loaded afer it if some config keys collide. Thus your getConfig() already affects the entire application and its scope is not limited to your module only.

Zend: Using forms in modules

I'm trying to use forms with modules, they should be stored inside the module. So at first my filestructure:
application/
(...other directories)
modules/
group/
controllers/
IndexController.php
(...controllers)
forms/
Create.php
views/
scripts/
(...view scripts)
Bootstrap.php
Within the IndexController, I'm trying to set the Form by
new Group_Form_Create()
and the class in Create.php is of course Group_Form_Create. I get the following error message:
Fatal error: Class 'Group_Form_Create' not found in (...)\application\modules\group\controllers\IndexController.php on line 380
The Bootstrap.php with the class Group_Bootstrap is just an empty class.
Actually, I'm using the default Zend structure, but it woun't work anyway. Any ideas wheres the problems or what could be a possible solution?
In my module bootstrap (APPLICATION_PATH/modules/group/Bootstrap.php), if use the following code:
//Loads the autoloader resources
$this->_moduleName = 'group';
$resourceLoader = new Zend_Loader_Autoloader_Resource(array(
'basePath' => APPLICATION_PATH ."/modules/".$this->_moduleName."/",
'namespace' => '',
'resourceTypes' => array(
//Tells the application where to find the forms
'form' => array(
'path' => 'forms/',
'namespace' => ucfirst($this->_moduleName).'_Form_'
),
//Tells the application where to find the models
'model' => array(
'path' => 'models/',
'namespace' => ucfirst($this->_moduleName).'_Model_'
)
)
));
I then call the forms or models like this:
$frm = new Group_Form_Create();
I use the same snippet in all my modules and I only change the value of the $this->_moduleName; each time.
Hope this helps !
It sounds like your module bootstraps are not being run. These are triggered by the module resource, which is loaded if you have:
resources.modules[] = ""
in your application.ini. So add this if it is not present.
Ideally, it should work out of box.
Add this in your bootstrap:
protected function _initAutoload() {
$autoloader = new Zend_Application_Module_Autoloader(array(
'namespace' => 'Group_',
'basePath' => dirname(__FILE__),
));
Zend_Loader_Autoloader::getInstance()->setFallbackAutoloader(true);
return $autoloader;
}

Zend Framework - Best Way To Autoload From /Application/Api Folder

I'm trying to autoload Classes from within a folder contained in the application itself.
E.G.
/Application
|->Models
|->Custom
|->Object.php
Is this the best way to do it (from bootstrap.php)?
public function _initAutoLoad()
{
$resourceLoader = new Zend_Loader_Autoloader_Resource(array(
'basePath' => APPLICATION_PATH,
'namespace' => '',
'resourceTypes' => array(
'custom' => array(
'path' => 'custom/',
'namespace' => 'Custom',
))
));
}
Meaning from within any controller, I can call:
$object = new Custom_Object();
If you're not intending to prefix the class names with the application namespace (default Application), I'd simply put this stuff in library, eg
library/
Custom/
Object.php -> class Custom_Object
then add your Custom namespace to the autoloader in configuration (application.ini)
autoloadernamespaces[] = "Custom_"
If your class represents some kind of service, you could use the built-in Service resource type which is automatically autoloaded
application/
services/
Object.php -> class Application_Service_Object
Looks like the solution I had is the best... I can find anyways...

Zend Form Custom Validation Path issues

The issue:
Plugin by name 'Spam' was not found in
the registry; used paths:
Zend_Validate_: Zend/Validate/
I have this on my bootstrap.php file (it's NOT a class):
include_once 'config_root.php';
set_include_path ( $PATH );
require_once 'Initializer.php';
require_once "Zend/Loader.php";
require_once 'Zend/Loader/Autoloader.php';
// Set up autoload.
$loader = Zend_Loader_Autoloader::getInstance ();
$loader->setFallbackAutoloader ( true );
$loader->suppressNotFoundWarnings ( false );
//resource Loader
$resourceLoader = new Zend_Loader_Autoloader_Resource(array(
'basePath' => APPLICATION_PATH,
'namespace' => '',
));
$resourceLoader->addResourceType('validate', 'validators/', 'My_Validate_');
$loader->pushAutoloader($resourceLoader);
I've named a file called Spam.php like this:
application/validators/Spam.php
class My_Validate_Spam extends Zend_Validate_Abstract {
On the form class I have:
//HONEY POT
$this->addElement(
'text', 'honeypot', array(
'label' => 'Honeypot',
'required' => false,
'class' => 'honeypot',
'decorators' => array('ViewHelper'),
'validators' => array(
array(
'validate' => 'Spam'
)
)
)
);
With all this, I'm getting:
Plugin by name 'Spam' was not found in
the registry; used paths:
Zend_Validate_: Zend/Validate/
Why ?
Thanks a lot.
You have to add the directory where you have your custom validators to your form elements prefix path. For example:
$elementPrefixPaths =
array(
array(
array(
'prefix' => 'My_Validate_',
'path' => 'My/Validate', // 'application/validators' in your case
'type' => 'validate',
)
)
);
$form->addElementPrefixPaths($elementPrefixPaths);
// or, if your're inside the form,
// $this->addElementPrefixPaths($elementPrefixPaths)
// before any elements make use of the validator.
The 'path' should be in your include path. You have to do the same with your custom filters. Also there is a similar approach for custom decorators and elements (which use the method setPrefixPaths() instead).
Read more here.
Your path is 'application/validators', but it would be better to follow ZF convention on class naming and path mirroring; as such you should put your validator in a directory such as 'My/Validate' You should follow this convention on all custom ZF extensions you develop (filters, helpers, plugins, etc). It will make your life easier in the long run. Also, as a final suggestion, don't use "My_" as your classes prefix, use something more personal, such as "Mem_" (considering your nickname).