ZF Namespace Autoloader en Bootstrapping - zend-framework

I have a standard ZF structure
library
-wil
-Auth
-Adapter.php
In this folder /libary/Wil/Auth/Adapter I have this class
based on http://www.zendcasts.com/logging-in-users-using-doctrine-and-zend_auth/2010/01/
class Wil_Auth_Adapter implements Zend_Auth_Adapter_Interface
{
}
and in the application.ini I declare my autoloaderNamespaces[]="Wil"
I have nothing in the bootstrap to register it as a Helper Broker or anything.
My question is why does it work when i call it from a controller
like so $adapter = new Wil_Auth_Adapter()
It is probably clear that I don't understand the autoloader & resources & bootstrapping in ZF.
Where can I get a good explanation of the process?

The autoloader automatically includes classes when they are first used. Resources are 'things' that the application uses such as a database connection, cache, autoloader. The bootstrap process sets up these resources. So these are three separate things but they are linked.
Your auth adapter is just a class, so it doesn't need any special setup via. brokers. The autoloader knows that a class called Wil_Auth_Adapter will live at Wil/Auto/Adapter.php, and it checks through the folders on the include_path (which include the library folder by default) for that class.

Related

Where to put a class that is not a controller, module or view?

I have a ZF2 application made of several modules, and I want to create a Logger class that should be accessible from any of these modules. Basically, I want to be able to log from anywhere with a simple Logger::info("Something").
The current application layout is like this:
root/
module/
module1/
src/
module2/
src/
module3/
src/
Where would be the best place to put this new logger class? And how to make sure it is accessible from any of the sub-modules?
I would suggest using the ServiceManager rather than calling a static method, this will allow you to more easily swap out the logging class if needed going forward.
Also ZF2 modules are quite flexible in terms of how code can be structured, so you could simply use:
module/Application/src/Application/Logger/LoggerFactory.php
Or perhaps create a Logger module if you see this code being reused in other projects.
I did see a blog post from Rob Allen yesterday regarding directory structure of modules - http://akrabat.com/zend-framework-2/thoughts-on-module-directory-structure/ - it may be worth having a quick read.
I put general classes that should be acceible by all under module/Application/src/WhateverName
For example, I put the auth class under:
module/Application/src/Application/Authentication/AuthenticationService.php
With the namespace:
namespace Application\Authentication;
And then I define the service in the Module.php
public function getServiceConfig()
{
return array(
'factories' => array(
'auth_service' => function ($sm) {
$zfauthservice = new \Zend\Authentication\AuthenticationService;
return new \Application\Authentication\AuthenticationService($zfauthservice, $sm->get('bp_user_mapper_model'));
},
);
}

ZF Include path

Is it correct to require_once?
where and how would you put it include path?
Should it not be in a application.ini or bootstrap?
EXAMPLE:
require_once 'Zend/View/Helper/Abstract.php';
// #question - is this correct - where and
// how would you put it include path
class Zend_View_Helper_Translate extends Zend_View_Helper_Abstract
{
}
Generally speaking, you can avoid require_once calls almost entirely by appropriately using Zend_Loader_Autoloader. Of course, the key is "appropriate".
Typically, your public/index.php sets the include_path to be the library folder. Then, if you are using Zend_Application, the Zend_Loader_Autoloader is registered to find any PSR-0 compliant classes whose namespace prefixes have been registered using the autoloadernamespaces array in application/configs/application.ini.
The tricky part is for classes defined in files that don't "reside on the include_path", like models that appear in application/models, services that reside in application/services, etc. Even though the classes defined there tend to follow PSR-0 standards, the fact that the PSR-0 mapping occurs relative to a base off the include-path means that the system has to know the mapping between classname prefixes and base paths. This is where resource autoloaders come in. These resource autoloaders are typically set up automatically in the application Bootstrap extending Zend_Application_Bootstrap_Bootstrap and module bootstraps that extend Zend_Application_Module_Bootstrap.
View helpers are another example of classes that reside "off the include_path", perhaps in something like application/views/helpers. Since these are typically invoked in a view script using a short form $this->someHelper($someParam), the system must be told how to generate the fully qualified classname from this short name. This is accomplished using $view->addPrefixPath() which maps namespace prefixes to filesystem locations. Again, the app-level and module level bootstrapping mechanism sets most of these up for you.
For libraries/classes that do not follow PSR-0 standards, you can create custom autoloaders and attach them (typically at Bootstrap) to the Zend_Loader_Autoloader singleton. This is the only place where you would have an explicit include/require.
tl;dr: With proper use of the existing ZF autoloader mechanism, you almost never need to have include/require statements in your own application code.
It is not correct in this case.
First off, please use Zend Tool. It will create the files you don't know how to create yourself. It will create the correct class names, extend them appropriately and require_once anything that might be needed.
Do not place require_once in the bootstrap. You want it to execute only when needed, not with every request.
As for the example you've provided, the correct version would be:
require_once "Zend/View/Interface.php";
class Zend_View_Helper_Foo extends Zend_View_Helper_Abstract {
}
The class that is extended by the helper is autoloaded and putting it in require_once does nothing.

How to use a model class from a module in the application bootstrap in a Zend Framework based application?

I am developing a Zend Framework MVC application with some modules, in example, the Users module. There is a model class name "Users_Model_User" that can be used in any module/controller operation. But I need to use an instance of that model in the application Bootstrap class, but there I get an exception:
Fatal error: Class 'Users_Model_User' not found in /my/path/...
I have a Bootstrap class for each module:
class Users_Bootstrap extends Zend_Application_Module_Bootstrap {
protected function _initAutoloader() {
$autoloader = new Zend_Application_Module_Autoloader(array(
'namespace' => 'Users_',
'basePath' => APPLICATION_PATH . '/modules/users'
));
return $autoloader;
}
}
and as I said, the modules are working just fine (reciving requests, processing and returning responses). I think this works fine due to the module bootstrap class, that takes care of loading the default module resources, like model classes. But the main Bootstrap class seems to lack of access to the "Users" module model classes.
Users_Bootstrap is executed after your application bootstrap, which means that your _initAutoloader() method hasn't been executed yet in your application bootstrap.
A solution could be to move your code from _initAutoloader() to your main bootstrap. This will solve your problem! You could also mean the piece of code in your main bootstrap to your module bootstrap, this will even make more sense to me. Note that all your modules bootstrap are always called, independently to the current module requested.
Also, let me share with you this article about the bootstrapping process in ZF, hope it will help you ;)
you could try(not sure it will work)
protected function __initSomething()
{
$this->bootstrap('autoload');
$model = new Users_Model_User();
...
}
i don't think bootstrap is a good place to do mysql queries, you should use a Zend_Controller_Plugin_Abstract, that way the resources are initiated and the bootstrap autoload is working(i'm using a plugin myself to do queries and check for permissions...)

Class resource_model_resource mapper not found in zend framework

I have redirected to resource module from indexController using following code:
$this->_helper->redirector->gotoSimple('view-resource', 'Resource', 'Resource', array());
where view-resource is action and Resource is controller and Resource is module.it is redirecting correctly.Now in view-resource action I have following code:
public function viewResourceAction()
{
$region=new Resource_Model_ResourceMapper();
}
Now error occurs as Resource_Model_ResourceMapper not found.Why this??When I check .zfproject,It contains the mapping of Resource module and it specifies as
<controllerFile controllerName="Resource"> <actionMethod actionName="index"/> <actionMethodactionName="viewResource"/>
<modelFile modelName="ResourceMapper"/>
That means it should recognize ResourceMapper but it does not find why??
My second question is:------ If I want to delete any action then it has to be deleted manually in .zfproject file. There should be some command,shouldnt be??
Thanks
Make sure your resource module contains a Bootstrap.php with a class Resource_Bootstrap extends Zend_Application_Module_Bootstrap {}
In your application.ini you at least need to have resources.modules[] =
The modules resource (Zend_Application_Resource_Modules) is responsible for creating instances of each module bootstrap class. Each module bootstrap class will create a module autoloader (Zend_Application_Module_Autoloader), responsible for autoloading the module based classes like Resource_Form_A, Resource_Model_B and Resource_Service_C.
To answer your second question; Zend_Tool is extremely limited in its usage. To maintain .zfproject.xml you have to do most of it by hand. In my opinion there are no real benefits for using Zend_Tool to create and maintain your project. Now worth the trouble.

How to add new class and autoload in zend framework

I am new on Zend framework and using first time it. I am looking for simple basic tutorials which I can read in very short time. I also stuck on if I want to add new class in Zend library. And it should also auto load when I make any new controller.
Please give your opinions if you have.
Regards,
This helped me At the beginning:
http://www.zendcasts.com/
http://devzone.zend.com/search/results?q=autoload (just search)
As autoload your class, This is the my way:
Create folder 'My' into library/
in it create folder 'Utils' and in Utils file 'Utils.php' so the path is library/My/Utils/Utils.php
For this path You must call class: class My_Utils_Utils{ ... }
and in configs/application.ini Put
appnamespace = "Application"
autoloaderNamespaces.my = "My_"
Then you can use namespace My_ and class My_Utils_Utils
In controller: $test = new My_Utils_Utils();
I am looking for simple basic tutorials
Here are a few tutorials I found while googling:
Official quickstart tutorial
A great book by frequent ZF-contributer PadrĂ¡ic Brady: Survive the deep end!
http://akrabat.com/zend-framework-tutorial/
Page with different tutorials: ZFTutorials.com
I also stuck on if I want to add new class in Zend library
You should not add new classes to the library per se, but instead create your own library or add classes in the "models"-folder/folders (if you use the modular project layout). Autoloading is achieved by utilizing Zend_Loader_Autoloader and its subclasses. As long as you follow the PEAR convention, i.e. if you have a class MyLib_Database_Table, then it should be inside the folder MyLib/Database, and the filename should be Table.php. (also make sure that the parent folder of MyLib is on the project include path.
To autoload simply use new MyLib_Database_Table, and the autoloader will load the class behind the scenes if necessary. Since 1.10 (I think), the autoloader also fully support PHP 5.3 namespaces. I.e:
// Filepath: lib\MyLib\Database\Table.php
namespace MyLib\Database;
class Table {
}
will work with the same folder structure. Code example:
use MyLib\Database\Table;
class IndexController extends Zend_Controller_Action
{
public function indexAction ()
{
$myTable = new Table();
}
}
auto load when I make any new controller
I'm not quite sure what you mean here. ZF does not have any dependency injection setup per default. But you can instantiate your classes without requiring them first if that's what you mean.