Using forms with the Zend Framework - zend-framework

I'm relatively new to MVC and the Zend Framework. That being said, I feel like I have a hard time figuring out where Forms belong in my directory structure. I have a modular directory structure, so I don't know if there should be a single forms directory, or one within each module directory.
/application
/modules/
/default
/controllers
/views
/admin
/controllers
/views
Once you've decided a directory for forms, do you set that directory in the include path of the bootstrap? Or do you include the form in the controller that it's being used in?
How do you use forms with the Zend Framework?

It's a little late but in the current version of ZF this has been solved:
On the following page http://framework.zend.com/manual/en/zend.loader.autoloader-resource.html
The manual states:
30.3.2. 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:
api/ => Api
forms/ => Form
models/ => Model
DbTable/ => Model_DbTable
plugins/ => Plugin
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.
This does, however, require the use of Zend_Application

add this in application/modules/yourmodule/Bootstrap.php file.
class Yourmodule_Bootstrap extends Zend_Application_Module_Bootstrap
{
protected function _initAutoload()
{
$autoloader = new Zend_Application_Module_Autoloader(array(
'namespace' => 'Yourmodule_',
'basePath' => APPLICATION_PATH .'/modules/yourmodule',
'resourceTypes' => array (
'form' => array(
'path' => 'forms',
'namespace' => 'Form',
),
'model' => array(
'path' => 'models',
'namespace' => 'Model',
),
)
));
return $autoloader;
}
}

As of March '09 the ZF thought leaders still seem to be debating the best ways to organize everything. There is a scaffolding-generator as a part of Zend_Tool slated for release in ZF v1.8. It's currently in the incubator, I tried it last week and it works, but there are not many components generated in its current state.
From the examples I've seen it seems that they are best managed separate from the models they interact with (this is from Zend Framework In Action):
/application
/modules/
/default
/controllers
/forms
ContactForm.php
LoginForm.php
RegisterForm.php
SupportForm.php
/models
Comment.php
User.php
Users.php
/views
/admin
/controllers
/views
However, I've also seen structured with the forms below the model directory. Matthew Weier O'Phinney shows how to use them for validation on models themselves:
/application
/modules/
/default
/controllers
/models
Comment.php
User.php
/Form
Comment.php
Login.php
Register.php
/views
/admin
/controllers
/views
To have your files automatically included be sure to name your classes using the underscore model.
For example, when Zend_Loader sees
class RegisterController extends Zend_Controller_Action
It looks in the php include_path for:
Zend/Controller/Action.php
Similarly, assuming the first structure above, if we include the 'default' module in our include_path:
# bootstrap.php
$rootDir = dirname(dirname(__FILE__));
define('ROOT_DIR', $rootDir);
set_include_path(get_include_path()
. PATH_SEPARATOR . ROOT_DIR . '/library/'
. PATH_SEPARATOR . ROOT_DIR . '/application/modules/default/'
);
include 'Zend/Loader.php';
Zend_Loader::registerAutoload();
You name your classes:
Forms_ContactForm
Models_User
Some programmers choose to put most of their files in the library so they don't have to add extra include paths:
/library
/My
/Form
Contact.php
Assuming the library folder is included, the class above would be named:
My_Form_Contact
Best of luck! -Matt

i personally like to keep them in my application folder, since i dont think they belong in the library and having just one folder makes autoloading them easier.
/application
/forms
/modules/
/default
/controllers
/views
/admin
/controllers
/views
/libray/
/Zend
and i just added the form path to the includes_path and i am good to go.

Personally, I found it easiest to put my module directory in the include path and name my form classes in the Zend Loader pattern.
Example directory structure (copying from Matt's answer):
/application
/modules/
/default
/controllers
/forms
Contact.php
Login.php
Register.php
Support.php
/models
Comment.php
User.php
Users.php
/views
/admin
/controllers
/views
Example form class names:
Default_Forms_Contact
Default_Forms_Login
Default_Forms_Register
Default_Forms_Support
I name my models and plugins similarly to keep things simple.
I hope this issue is addressed correctly in later versions of the Zend Framework.
UPDATE:
This structure doesn't work on *nix platforms. Found that out the hard way! The Zend Loader needs the module, forms, and models folders to be capitalized to work in a case sensitive environment.

the zend command tool can create forms for that:
zf create form product sales
where sales is the name of the module, the command tool create a directory form inside module sales and a file Product.php with a class:
class sales_Form_Product extends Zend_Form {
and you have to add a definition of de Zend_Application_Module_Autoloader, to define your module's directory

$selectexamname = new Admin_Form_examresults_Selectexamname();
$this->view->selectexamname = $selectexamname;
your class should have to define according to this format
class Admin_Form_examresults_Selectexamname extends Zend_Form {}

I put all my models in a folder in the library. Notion is my company's name.
/application
/modules/
/default
/controllers
/views
/admin
/controllers
/views
/libray/
/Zend
/Notion
/Form
This makes it easy to include and find files as you already have the library folder included.
Notion_Form_Login
Notion_Db_Manager_Login

Related

Zend Framework 3 share doctrine models between modules of the same project

I am new into Zend Framework 3 programming.
Previously we create a project having all database table's mapping included in one particulare module.
Now, we need to create another module into the same project. So we would like to put outside from the first module the database mapping objects in order to shared tha classes between the both modules.
I try to create a new module only for the mapping, but without succes. The namespaces doesn't existes.
After I look for solution like using ServiceManager, but I didn't really understand how to used it.
Do you know if there is another solution than using a ServiceManager ? And if not, have I change all my previous code using objects included simply with the key word use, in order to use the ServiceManager ?
Thanks.
Finaly in my solution I create a module containing only the sources files for the doctrine mapping under src directory.
/module
/MyApplication
/src
/config
/module.config.php
/Common
/src
/DoctrinMapping
/Entities
composer.json
In composer.json I put :
"autoload": {
"psr-4": {
"MyApplication\\": "module/MyApplication/src/"
,"Common\\":"module/Common/src/"
}
}
At the project root I execute the commande line :
composer dump-autoload
After into module.config.php of the my specifique application I define the doctrine reference as :
,'doctrine' =>
[
'driver' =>
[
'common_entities' =>
[
'class' => 'Doctrine\ORM\Mapping\Driver\AnnotationDriver'
,'cache' => 'array'
,'paths' => array(__DIR__ . '/../../Common/src/DoctrineMapping/Entities')
],
'orm_default' =>
[
'drivers' =>
[
'Common\DoctrineMapping\Entities' => 'common_entities'
]
]
]
]
That works, but I don't know if this is the best solution to apply.

Zendframework(1.12.11) view helper not found in phpunit

I have following directory structure for view helper in my zendframework project
--application
--views
--helpers
--Test.php
and configuration setting in application.ini is
resources.view.helperPath = APPLICATION_PATH "/views/helpers"
and configuration in Bootstrap.php is
$view->setHelperPath(APPLICATION_PATH . "/views/helpers/");
in Test.php file naming convention is
class Zend_View_Helper_Test extends Zend_View_Helper_Abstract {}
and I am using helper function in module wherever I need it.When I run project via browser, application working fine without any error, but when I invoke phpunit for same application via command line I am getting error something like
Fatal error: Uncaught exception 'ErrorException' with message 'include_once(Zend\View\Helper\Test.php): failed to open stream: No such file or directory' in D:\
zend\ZendServer\share\ZendFramework-1.12.11\library\Zend\Loader.php:134
that means it's going to find Test.php file in zend server library view folder.I am not getting why it's working via browser and not working in phpunit via command line.
I got solution. I have replace my configuration setting of application.ini
resources.view.helperPath = APPLICATION_PATH "/views/helpers"
with
resources.view.helperPath.Application_View_Helper = APPLICATION_PATH "/views/helpers/"
and changed naming convention of Test.php with
class Application_View_Helper_Test extends Zend_View_Helper_Abstract {}
now zend loder will try to find view helper in application directory rather than Zend

Use default module's action helpers in another module with Zend Framework

I think I've tried everything I've found to solve this, including all the answers here on SO.
In my project there is an admin module, and then there's the default module. Now I want the admin module to use the default module's helpers. Preferably only if there isn't an admin module helper with the same name. Is this possible?
The error message I get is:
Message: Plugin by name 'HeadBase' was not found in the registry; used
paths: Admin_View_Helper_:
/application/modules/admin/views\helpers/
Zend_View_Helper_: Zend/View/Helper/
I use ZF 1.11
Found a solution. In the Bootstrap, add an init for helpers, like this:
protected function _initHelpers()
{
$this->bootstrap('view');
$view = $this->getResource('view');
$view->addHelperPath(APPLICATION_PATH . '/views/helpers/', 'Zend_View_Helper');
}
This adds the helper path APPLICATION_PATH . '/views/helpers/' for helpers whose class is prefixed with Zend_View_Helper.

Zend Framework + Doctrine1.2 project structure with more modules

applications coupled with the realization ZendFramework + Doctrine 1.2 for some time, but now they have their first experience with the use of more modules. I requested a default module is visible to everyone with a certain layout and an admin module with a different layout.
So far in my applications I have always used the following structure:
/app
/application
/acls
/configs
/controllers
/forms
/layouts
/models --> models by doctrine
/generated --> base models by doctrine
/plugins
/views
/Bootstrap.php
/data
/doctrine
/data
/migrations
/schema
/schema.yml
/doctrine.php
/library
/public
/tests
So my question is: how should the structure of my application to do what is required?
I tried using zend tool and see what kind of structure I created the command:
zf create module admin
course after launching
zf create project app
I noticed that the create command module I created a folder modules in application.
Into modules created admin and inside it has created controllers, models and views.
So in addition to separating means zf controller and view correctly, but also models.
But my doctrine creates all the models on the one hand! :D
How can I do to use templates created by doctrine for each module?
Then how do I assign a new layout for the admin module?
For the party guest you advise me to leave the facility that currently use or move it all in a form default?
Sorry if I made a lot of questions, maybe too much, but I am really very confused about it!
Thanks
After a thorough documentation I've found the right project structure
/app
/application
/acls
/configs
application.ini
/layouts
/scripts
admin.phtml
default.phtml
/models --> models by doctrine
/generated --> base models by doctrine
/modules
/admin
/controllers
/forms
/view
/default
/controllers
/forms
/view
/plugins
/Bootstrap.php
/data
/doctrine
/data
/migrations
/schema
/schema.yml
/doctrine.php
/library
/public
/tests
To view a different layout according to where you are module I used the following plugins:
class Plugin_Layout extends Zend_Controller_Plugin_Abstract
{
/**
* Called before an action is dispatched by Zend_Controller_Dispatcher.
*
* #param Zend_Controller_Request_Abstract $request
* #return void
*/
public function preDispatch(Zend_Controller_Request_Abstract $request)
{
$layout = Zend_Layout::getMvcInstance();
$module = $request->getModuleName();
switch ($module) {
case 'default':
$layout->setLayout('default');
break;
case 'admin':
$layout->setLayout('admin');
break;
default:
$layout->setLayout('default');
break;
}
}
}
into Bootstrap.php file
/**
* #return Zend_Application_Module_Autoloader
*/
protected function _initAutoload()
{
$autoloader = new Zend_Application_Module_Autoloader(array('namespace' => '', 'basePath' => APPLICATION_PATH));
$autoloader->addResourceType('plugin', 'plugins', 'Plugin');
return $autoloader;
}
into application.ini file
resources.frontController.plugins.auth = Plugin_Layout
resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts/"
the plugin described above according to the module in use will set the layout with the name of module.phtml within "layouts/scripts".
How to Autoload forms within a module
add the two below lines to your application.ini file
resources.frontController.moduleDirectory = APPLICATION_PATH "/modules"
resources.modules[] = ""
Create a boostrap file for each module. The file, named Bootstrap.php, should be placed in the root of the module directory and the class name should be {module name}_Boostrap. This bootstrap file will cause zend framework to automatically add the new forms directory to the autoloader.
class Admin_Bootstrap extends Zend_Application_Module_Bootstrap {}
Add for form class to the /forms directory. A login form would have a filename of Login.php and a class name of {module name}_Form_Login
class Admin_Form_Login extends Zend_Form
Call your form from a controller file from within the same module
$form = new Admin_Form_Login();
Simple and effective! ;)

How to change include directory of Zend Framework

I get the following error messages:
Warning: include_once(Zend\Db.php) [function.include-once]:
failed to open stream: No such file or directory in
C:\EasyPHP3\www\VPZ\Lib\Zend_1.7.7\Loader.php on line 83
Warning: include_once() [function.include]:
Failed opening 'Zend\Db.php' for inclusion (include_path='VPZ/') in
C:\EasyPHP3\www\VPZ\Lib\Zend_1.7.7\Loader.php on line 83
Warning: require_once(Zend/Exception.php)
[function.require-once]: failed to open stream:
No such file or directory in
C:\EasyPHP3\www\VPZ\Lib\Zend_1.7.7\Loader.php on line 87
Fatal error: require_once() [function.require]:
Failed opening required 'Zend/Exception.php' (include_path='VPZ/') in
C:\EasyPHP3\www\VPZ\Lib\Zend_1.7.7\Loader.php on line 87
i want to include ZendXXX\Db.php
how to change it
create a directory (say 'lib'), and put your Zend directory in it. so your directory structure looks like this:
- application
- lib
|- Zend
- wwwroot
|- index.php
now you should add lib to your include path. edit your index.php file:
$includePath = array();
$includePath[] = '.';
$includePath[] = './../application';
$includePath[] = './../lib';
$includePath[] = get_include_path();
$includePath = implode(PATH_SEPARATOR,$includePath);
set_include_path($includePath);
now you have your lib in your include path. you can include all Zend components like this:
include 'Zend/Loader.php';
require_once 'Zend/Db.php';
the best way is too include Zend_Loader first and then use it to load classes. do this:
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Db');
you can also register to autoload classes. just add this line to your code after all those before:
Zend_Loader::registerAutoLoad('Zend_Loader',true);
now you do not need to include files to call classes. just instanciate your classes:
$session = new Zend_Session_Namespace('user');
there is no need to include 'Zend/Session/Namespace.php'.
Use set_include_path(). See PHP.net documentation
Example:
set_include_path(get_include_path() . PATH_SEPARATOR . '/path/to/Zend');
I usually store the framework files under a "library" folder:
application
public_html
library
Zend
Common
etc....
and then in my bootstrap file, or front controller, I add that "library" folder to the include path:
set_include_path(get_include_path() . PATH_SEPARATOR . '../library');
See also:
Choosing Your Application's Directory Layout.
Create the Filesystem Layout.
The reason the other suggestions say anything about doing that, is because it's a bad move - in other words, you're doing it wrong.
You can create a subdirectory and name it Zendxxx, but then you have to add that to your include_path, and change it, whenever you put a newly named version up.
I'd hazard a guess, and say that you don't have a good way to test the website (so you want to lock it to a particular version of ZF), and further, that you aren't using revision control, so you want all the previous versions of code in the site-directory to be able to go back to, if you find a problem when you change the live-running code directly on the server.
project without library And including library from one location
project C:\xampp\htdocs\my\application
library C:\xampp\Zend\library
make changes in index.php
// Ensure library/ is on include_path
set_include_path(implode(PATH_SEPARATOR,
array(realpath(APPLICATION_PATH.'/../../../Zend/library'),get_include_path(),)));