Zend Framework 2 : Step by Step build Form using Annotation Builder
Zend Framework provide AnnotationBuilder that can createForm by entity which we defined. An entity can be one class that consists of Annotation Type, Filter, Validator, etc in each of the properties. This feature need doctrine Annotation. In this post, i will give you step by step how to use this annotation .
1. First, grab skeleton application from github.
git clone git://github.com/zendframework/ZendSkeletonApplication.git cd ZendSkeletonApplication
2. Add doctrine/common to composer.json
{ "repositories": [ { "type": "composer", "url": "http://packages.zendframework.com/" } ], "name": "zendframework/skeleton-application", "description": "Skeleton Application for ZF2", "license": "BSD-3-Clause", "keywords": [ "framework", "zf2" ], "homepage": "http://framework.zend.com/", "require": { "php": ">=5.3.3", "zendframework/zendframework": "2.*", "doctrine/common" : ">=2.1" } }
3. run install by :
COMPOSER_PROCESS_TIMEOUT=5000 php composer.phar install
The process will be like the following :
4. Let’s code :
a. create an entity
namespace SampleModule\Model; use Zend\Form\Annotation; /** * @Annotation\Hydrator("Zend\Stdlib\Hydrator\ObjectProperty") * @Annotation\Name("Student") */ class Student { /** * @Annotation\Type("Zend\Form\Element\Text") * @Annotation\Required({"required":"true"}) * @Annotation\Filter({"name":"StripTags"}) * @Annotation\Filter({"name":"StringToUpper"}) * @Annotation\Validator({"name":"StringLength", "options":{"min":"5"}}) * @Annotation\Options({"label":"Absent Id:"}) */ public $absentid; /** * @Annotation\Type("Zend\Form\Element\Text") * @Annotation\Required({"required":"true" }) * @Annotation\Filter({"name":"StripTags"}) * @Annotation\Validator({"name":"StringLength", "options":{"min":"1"}}) * @Annotation\Options({"label":"Name:"}) */ public $name; /** * @Annotation\Type("Zend\Form\Element\Radio") * @Annotation\Required({"required":"true" }) * @Annotation\Filter({"name":"StripTags"}) * @Annotation\Options({"label":"Gender:", * "value_options" : {"1":"Male","2":"Female"}}) * @Annotation\Validator({"name":"InArray", * "options":{"haystack":{"1","2"}, * "messages":{"notInArray":"Gender is not valid"}}}) * @Annotation\Attributes({"value":"1"}) */ public $gender; /** * @Annotation\Type("Zend\Form\Element\Select") * @Annotation\Required({"required":"true" }) * @Annotation\Filter({"name":"StripTags"}) * @Annotation\Options({"label":"Class:", * "value_options" : {"0":"Select a Class","1":"A","2":"B","3":"C"}}) * @Annotation\Validator({"name":"InArray", * "options":{"haystack":{"1","2","3"}, * "messages":{"notInArray":"Please Select a Class"}}}) * @Annotation\Attributes({"value":"0"}) */ public $class; /** * @Annotation\Type("Zend\Form\Element\Submit") * @Annotation\Attributes({"value":"Submit"}) */ public $submit; }
b. Call it in controller
namespace SampleModule\Controller; use Zend\Mvc\Controller\AbstractActionController; use Zend\Form\Annotation\AnnotationBuilder; use SampleModule\Model\Student; class StudentController extends AbstractActionController { public function addAction() { $student = new Student(); $builder = new AnnotationBuilder(); $form = $builder->createForm($student); $request = $this->getRequest(); if ($request->isPost()){ $form->bind($student); $form->setData($request->getPost()); if ($form->isValid()){ print_r($form->getData()); } } return array('form'=>$form); } }
c. show it in the view :
$form = $this->form; $form->setAttribute('action', $this->url( 'SampleModule/default', array( 'action' => 'add', 'controller' => 'student' ) )); $form->prepare(); echo $this->form()->openTag($form); echo $this->formCollection($form); echo $this->form()->closeTag();
Done !
References :
1. http://mwop.net/blog/2012-07-02-zf2-beta5-forms.html
[…] https://samsonasik.wordpress.com/2012/10/04/zend-framework-2-step-by-step-build-form-using-annotation… […]
[…] For example, i have the following form like this to utilize rememberMe() function for authentication with DbTable adapter : 1. Prepare a Login Form with this entity. […]
SALAM ALAYKOM ABUL MALEK happy EID ADHA MUBARAK ! thanks a lot for this great blog !
Wa’alaikumsalam, happy ied adha mubarak. Allohu Akbar Allohu Akbar Allohu Akbar, Laa ilaa haillallohu wallohuakbar Allohuakbar walillahilhamd. You’re welcome.
Sorry delete the previous post I was on the wrong tutorial. I posted it on the Zend Framework 2 : Using Zend\Form and Ajax.
ok, deleted 🙂
Hey
kindly give me the steps to develop a application in zf2 tutorial…..
Thanks in advance..
[…] 1. Prepare a Login Form with this entity. […]
Thank’s for your tutorials, dude! But i have 1 question – where i can find list of all options for annotations? I need more control to create elements (wrappers, classes, etc). Thank you!
read the docs : http://zf2.readthedocs.org/en/latest/modules/zend.form.quick-start.html?highlight=annotation#using-annotations
I’ve seen it… As i can see, there is one way for me – create forms via fabrics. Thank you
Hi! how do yo for validate a email
Hi,
Can u provide a post about generating an entities from existing database using a command line tool…
Thanks in advance
not yet, thanks for the suggestion 😉
Wow, great tutorial. Works fine… i tried to use annotation with a translator… first solution, dropping labels and setting them in the view, which works but… do you know a better way, especially when thinking about value_options in radio or select-elements!?
Kind regards from snowy Hanover, Germany
I’m not fan with AnnotationBuilder, just want to share the other options instead of extends Zend\Form\Form. for value_options, if values are come from db, i think you should extends Zend\Form\Form, and pass a db to the form.
Thanks for the comment 😉
What is your favorite method to create a form quickly ?
quicker is using config file via “form_elements” config, but will be more programmable with extends \Zend\Form\Form.
ok, i’m beginner in zf, but with annotation builder and doctrine it seems like a easy way to create a form, and i try to understand why you’re not fan.
in my case a want to create a back office, and a form based on entity doctrine make me automatique form with association mapping
@yves the question wasn’t addressed to me, but I think the answer for at least some people is that with annotations it’s harder to cache and (arguably) it blends different areas of responsibility into one place. For me, the attraction is greatest where the validation rules are intimately related to the database column definitions. Enforcing a maximum string length is a good example. When you’re using Doctrine, you likely have Doctrine annotations specifying the column width, and logical place for a string-length validator would be located right there in the same file — or so some people think. Makes it convenient in case you have to make a change to your schema.
gracias ¡¡¡
le invitamos
How to fill options from database?
look at manuel stosic’s blog post : http://samminds.com/2013/03/zendformelementselect-and-database-values/
@samsonasik Thank You! This is a great article, everything nicely explained, found few good hints here. But I have a question. I have two entities VpnServer and VpnClient, each VpnClient belongs to one VpnServer. The most important part is the client:
class VpnClient
{
/**
* @ORM\OneToOne(targetEntity="VpnServer")
* @ORM\JoinColumn(name="vpn_server_id", referencedColumnName="id")
* @Annotation\Type("Zend\Form\Element\Select")
* @Annotation\Options({"label":"VpnServer:"})
* @Annotation\Required({"required": true})
*/
private $vpnServer;
Of course I’m building the form with AnnotationBuilder from the entity. An my question: is it possible with ZF + Doctrine + Annotations to fill the shown above Zend\Form\Element\Select with values from the VpnServer table? Or do I have to do this by my own (I mean in the controller, before passing the form to the ViewModel)?
I’m not pretty sure about the right way to take this. but maybe, Manuel Stosic’s blog post can help you : http://samminds.com/2013/03/zendformelementselect-and-database-values/ see Doctrine\ObjectManager section.
Thank You, I’ll take a look. I like it to have it all in the entity, I mean the form, the validators, etc. Using ZF2 becomes real fun with Doctrine and Annotations.
COMPOSER_PROCESS_TIMEOUT=5000 php composer.phar install
‘COMPOSER_PROCESS_TIMEOUT’ is not recognized as an internal or external command,
operable program or batch file.
you’re using windows ? see this : http://getcomposer.org/doc/00-intro.md#installation-windows and this : http://diywebdev.com/setting-up-composer-php-dependencies-manager-in-windows/
Error: Add doctrine/common to composer.json
I don’t know add
or
add error:
D:\wamp\www\LVTN\TK\Zf2Demo>php composer.phar install
Loading composer repositories with package information
Installing dependencies from lock file
Warning: The lock file is not up to date with the latest changes in composer.jso
n. You may be getting outdated dependencies. Run update to update them.
Nothing to install or update
Generating autoload files
Please help ! (I am from VietNam) Thank you !
mail: daonhamphucbdvn@gmail.com
yahoo: goro_kolo@yahoo.com.vn
try php composer.phar update
but error
try remove your vendor folder, clear composer cache, and try again.
I try: php composer.phar update
but when I try: http://localhost/LVTN/TK/Zf2Demo/public/home/auth/login
then error:
Warning: require(D:\wamp\www\LVTN\TK\Zf2Demo\vendor/zendframework/zendframework/library/Zend/Stdlib/compatibility/autoload.php) [function.require]: failed to open stream: No such file or directory in D:\wamp\www\LVTN\TK\Zf2Demo\vendor\composer\autoload_real.php on line 41
Call Stack
# Time Memory Function Location
1 0.0017 672192 {main}( ) ..\index.php:0
2 0.0023 682648 require( ‘D:\wamp\www\LVTN\TK\Zf2Demo\init_autoloader.php’ ) ..\index.php:9
3 0.0030 685096 include( ‘D:\wamp\www\LVTN\TK\Zf2Demo\vendor\autoload.php’ ) ..\init_autoloader.php:14
4 0.0042 704232 ComposerAutoloaderInitfc7b3736a88486e977161f8d40605ff4::getLoader( ) ..\autoload.php:7
Fatal error: require() [function.require]: Failed opening required ‘D:\wamp\www\LVTN\TK\Zf2Demo\vendor/zendframework/zendframework/library/Zend/Stdlib/compatibility/autoload.php’ (include_path=’.;C:\php\pear’) in D:\wamp\www\LVTN\TK\Zf2Demo\vendor\composer\autoload_real.php on line 41
Call Stack
# Time Memory Function Location
1 0.0017 672192 {main}( ) ..\index.php:0
2 0.0023 682648 require( ‘D:\wamp\www\LVTN\TK\Zf2Demo\init_autoloader.php’ ) ..\index.php:9
3 0.0030 685096 include( ‘D:\wamp\www\LVTN\TK\Zf2Demo\vendor\autoload.php’ ) ..\init_autoloader.php:14
4 0.0042 704232 ComposerAutoloaderInitfc7b3736a88486e977161f8d40605ff4::getLoader( ) ..\autoload.php:7
Help
Can you add facebook of me : http://www.facebook.com/oppa.boo.1368
Thank’s you !
if you’re failed with composer, try another way, follow readme in this repo : https://github.com/zendframework/ZendSkeletonApplication#using-git-submodules
Why do you install doctrine? Can I use annotation builder without install doctrine?
because, in this case, I use annotation builder. no, we can not build annotation without doctrine at this case.
hi
iam very happy on seeing this most of my problems are solved
please provide me validation code for registration form links…..
validate link ? Just use Zend\Form\Element\Url
Hi, I try to reproduce it, but I get a checkbox instead of Zend\Form\Element\Radio. Thx.
checkbox must be named independently, should be set value, not value_options.
@ComposedObject adds another annotated class as a FieldSet. Is there an annotation to direct the AnnotationBuilder to add the other annotated class added as a FormCollection instead?
Edit: @ComposedObject adds another annotated class as a FieldSet. Is there an annotation to direct the AnnotationBuilder to add the other annotated class as a FormCollection instead?
sorry, i have no idea for now 🙂
thank you very much for all your perfect tutorials , plz i need to know the difference between required and allowEmpty Annotations . when i set required annotation to false i still have an error msg indicating that i should fill the input .
you need to set allowempty = true
You should use * @Annotation\AllowEmpty({“allowempty”:”true”}) instead of * @Annotation\Required({“required”:”true” })
Thanks! Life saver! I had been struggling with this for ages!
Hi,
i can’t get annotations to work, when generating form from annotations only empty fields are in form spec, I’ve copied the code from here.
I am using ZF 2.2.5, has something changed recently?
Any troubleshooting tips appreciated
do you use windows ? I’m not sure enough about windows ^^
yes, i’m on windows, does it matter? I’ve installed everything fine.
I’m trying to manually read annotations for Album class, using ClassReflection, and for a single property I’m having
object(Zend\Code\Scanner\AnnotationScanner)#255 (6) {
[“isScanned”:protected]=>
bool(false)
[“docComment”:protected]=>
string(95) “/**
*
* @Annotation\Required(false)
* @Annotation\Attributes({“type”:”hidden”})
*/”
[“nameInformation”:protected]=>
object(Zend\Code\NameInformation)#256 (2) {
[“namespace”:protected]=>
string(11) “Album\Model”
[“uses”:protected]=>
array(3) {
[“CherryTools\Model\AnnotatedModelFactory”]=>
string(21) “AnnotatedModelFactory”
[“Zend\InputFilter\InputFilterInterface”]=>
string(20) “InputFilterInterface”
[“Zend\Form\Annotation”]=>
string(10) “Annotation”
}
}
[“annotationManager”:protected]=>
object(Zend\Code\Annotation\AnnotationManager)#247 (1) {
[“events”:protected]=>
NULL
}
—– FU*K ———–
[“annotations”:protected]=>
array(0) {
}
—– FU*K ———–
[“storage”:”ArrayObject”:private]=>
array(0) {
}
}
okay, got it.
tip: use spaces, not tabs, as annotations parser won’t parse spaces 😛
Going further, when tokenizing in parser I’m having
array(2) {
[0]=>
string(17) “ANNOTATION_IGNORE”
[1]=>
string(46) ” * @Annotation\Attributes({“type”:”hidden”})
”
WTF 😛
* @Annotation\Required({“required”:”true” }) not work at submit form?
Please help me
how to bind single form with multiple entity using ZF2 with ORM doctrine2 for edit action in controller
Great tutorial, thank you!!
you’re welcome 😉
Great Abdul, I’ve copied and pasted your code and it simply doesn’t work, it seems that my annotations had been ignored and at the end I only have an empty fieldset “”. Is there any other dependency or even some sort of PHP extension that could be missing on my computer?
Remove zenddevelopertools from module array in application.config.php
Actually all you need to do is sent the “Events” -> “Enabled” option to false in the ZDT autoload configuration file. I’m not sure why this effects the loading of Annotations but at least you can keep ZDT.
As diemuzi said I just needed to set ‘Events’ => ‘Enabled’ = false, on ApplicationPath/config/autoload/zdt.local.php
Thanks a lot both of you guys. Now it’s finally working!
How can I pass id to the form for update the record?
http://framework.zend.com/manual/2.3/en/user-guide/forms-and-actions.html#editing-an-album
Hi my Friend , Your work is very helpful , But I wonder if i wont the user to be redirect to the Auth Form befor he can access any URL or multiple URLs in the Application , How that can be done in me Zend Application
there are other strategy, you can break it with “non-authorized” page.
Brother I have followed your steps of installation but not able to install, its giving me the following error
A 404 error occurred
Page not found.
The requested URL could not be matched by routing.
No Exception available
Please help me out!!!!
check your registered router, start learn from the docs http://zf2.readthedocs.org/en/latest/user-guide/routing-and-controllers.html
Hi…. how can we add class to ours form elements¡? with the AnnotationBuilder
Thank You in Advance
you probably find this http://blog.james-carr.org/2012/09/09/drying-up-your-zend-framework-2-models-with-annotations/
Hi Samsonasik,
does this also/still work in zend expressive 1.0?
Hello Samsonasik,
found the answer myself:
PHP7 is the problem: https://github.com/zendframework/zend-form/issues/51
Hello
How can we add validator UniqueObject?
I never use it, you probably find this: http://www.aronkerr.com/2013/11/zf2-form-collection-validation-unique.html
I don’t know if it’s a good idea, but i extend AnnotationBuilder, to attach my own ElementAnnotationsListener
and now it for doctrine validator it will object_repository find in metadata, inject fields find in inputSpec, and inject objectManager, set in constructor, like AnnotationBuilder from doctrine, it’s work now, but what do you think?
I’ve no idea about it, sorry…