Monday, December 10, 2012

Zend Framework 2 (ZF2) - Creating View Helpers and a Custom Captcha

Greetings Programs,
The code in this post is available here https://github.com/jdellostritto/zf2tutorial.git. This project represents my starting point for learning zf2. Feel free to use as needed.

Like ZF1 the captcha image has more than one input that is rendered one after the other. Styling can be challenging with this kind of layout. In this blog I demonstrate how to create an extended captcha image and a new view helper. Before I begin you might want to be aware of how the view helper system works. Here is how I understand it.

The stock captcha image(Zend\Captcha\Image.php) in ZF2 uses a view helper (Zend\Form\View\Helper\Captcha\Image.php).

The catpcha image also ( Zend\Captcha\Image.php) has a function name called 'getHelperName'. This function gives the renderer the view helper to render the catpcha. 'getHelperName' happens to return 'captcha/image' or and instace of this guy (Zend\Form\View\Helper\Captcha\Image.php).

If you look (using debug) the phpRenderer instance has the helper class called captchaimage as an invokable (found in the PhpRenderer::__helpers invokablesClasses). This invokable is the view helper we mentioned above (Zend\Form\View\Helper\Captcha\Image.php). Makes sense right... you create the image and the renderer is all ready there for us. This is just the image. As you are aware you have to give the image to a form element...

When you create your Captcha form element (Zend\Form\Element\Captcha.php) you  give the captcha image (Zend\Captcha\Image - what we just talked about) to it. We know it's all set because the renderer is already loaded. Well it's not what we want.

The 'form' element captcha has it's own helper (Zend\Form\View\Helper\FormCaptcha.php). In the render function of this helper you will see that the captcha image (zend\catpcha\image) is grabbed from the ElementInterface(line 33) and then the helper name via 'getHelperName' (line 42). Finally we retrieve a class instance of the helper from an instance of PhpRenderer and we rendered  the output (line 52 and 53).

In order to keep our sanity we have to keep separate the 'form element and view helper' from the 'captcha image an it's helper'. We give the captcha image to the form element captcha who already has a linked helper. The form element captcha render function will pull the instance of the captcha image we gave it, find it's view helper, and render it. All we really need to do is jump in here and give the captcha image a new helper that renders's the way we want and to override the captcha image preventing it from getting the original helper

Clear as mud right!
For our code we have to look at three things.
1: The view helper ('zend\form\view\helper\captcha\image' line 61) for the captcha defines a pattern for output as %s%s%s which produces what we already are aware of. So first thing's first we want is our own custom view helper with our own pattern. So we create one in our application module

module\Application\src\Application\View\Helper\Form\Custom\Captcha\ViewHelperCaptcha.php
...
Our view helper class above is a duplicate of the  Zend\Form\View\Helper\Captcha\Image.php class with a few exceptions. The first is that it does not use the Zend\Captcha\Image as this class points at a view helper found at Zend\Form\View\Helper\Captcha\Image. Remember that the Zend\Captcha\Image has a function called getHelperNames which returns a hardcoded helper name 'captcah\image' so when the form renders the image it will get the wrong helper. So the last two things we need to do is give the phpRenderer our custom view helper and create a new captcha image that extends the original Zend\Captcha\Image and overrides the setHelperName giving the new helper we just created. Notice lastly that we have changed the pattern in our helper above to put div's around our captcha elements.

Next we add our class to the view helpers in the phpRenderer invokables classes. This is done in module.config.php

...
The next step is to create  a captcha image that returns the view helper we have created and added to the phpRenderer's invokables class. We don't want to redefine the entire Captcha image we just need it to point to our custom view helper. To do this we are going to create  our custom class called CustomCaptcha.php here:
module\Application\src\Application\View\Helper\Form\Custom\Captcha\CustomCaptcha.php

We are going to extend the real Zend\Captcha\Image and override the 'getHelperName' so that it returns our  helper 'viewhelpercaptcha'.

...
The last thing we need to do is make sure we are using our CustomCaptcha image in our form. So here is a snippet of code from our RegisterForm.php in our user module that uses our custom captcha image and it's custom view.
...

Inspecting your structure the image and inputs are now wrapped in divs.

This makes for a more orderly design.



Dr. Lora Baines: You know, Flynn has been thinking about breaking into the system ever since Dillinger canned him. And he had Group 7 access.

Tron 1982.

Thursday, December 6, 2012

Zend Framework 2 (ZF2) - JavaScript and CSS Helper Class

Greetings Programs,

In Zend Framework 1.0 I used a CSS and JavaScript loader. This allowed me load CSS and JavaScript based on an action and a controller. It also allowed me to load common CSS and JavaScript required for my headers, footers, and other common components that might be found on a page. I wanted to try and repeat this in ZF2. In this post I will walk through how I accomplished this.

I am currently learning ZF2 and am building from the skeleton application and from Rob Allen's album application. You can get my code from https://github.com/jdellostritto/zf2tutorial.git.

The factory loaders (CssLoader.php, and JsLoader.php) are based on the an example provide by Evan Coury.
http://blog.evan.pro/creating-a-simple-view-helper-in-zend-framework-2


First create your PHP helper files in this location:

/module/Application/src/Application/View/Helper/JsLoader.php
/module/Application/src/Application/View/Helper/CssLoader.php 


In this next step we need to do two things in the onBootstrap function of the Applicaiton/Module class (found in project at: /module/Application/Module.php). First we 'attach' or 'hook' to a MvcEvent called EVENT_ROUTE. Which as I understand it signifies the completion of the route creation. In the function we attach to the EVENT_ROUTE we are going to create two factories that will be accessible to our view. The goals is for us to be able to call our JsLoader and CssLoader classes from our layout.phtml file.
...
On to the helpers. We created two helpers earlier so it's time to fill these in. We extend the AbstractHelper which provides us the prototype functions to use.  We send three arguments to the loaders. The Request, PhpRenderer, and a RouteMatch. Our constructor must accept each of these and make them available. The invoke function then does the work. In this example all we have done in both the CssLoader and JsLoader is move the original skeleton code loading of headLink and headScript from layout.phtml into these two handy loaders.

...
...
...
The last step is to replace the original headLink and headScript in our layout.phtml file.
...
I am diving in to ZF2 and am putting together what I can from many sources. If this approach is flawed or there is a better way to do it please leave a comment.

Crom: Look. This... is all a mistake. I'm just a compound interest program. I work at a savings and loan! I can't play these video games!
Tron: 1982

Monday, December 3, 2012

Zend Framework 2 (ZF2) - Validate a Check Box

If you have a registration form with a terms and conditions check box you'll probably want to validate that it is checked. This can be accomplished by using the Digits Validator.

Start by defining your input as follows: ...

Notice that the checked_value = 1.
Notice also that the unchecked_value = 'no'.
Look at the Zend\Validator\Digits class and notice that it validates the following:
...

The check box will fail validation when it is 'unchecked' because it contains the alpha characters ('no'). So next we create our input filter for our terms check box and give the 'NOT_DIGITS' our custom message.
...

I am still a little bummed out that decorators are no longer used but am impressed with some of the new capability provided by ZF2.


Master Control Program:  You're in trouble, program. Why don't you make it easy on yourself. Who's your user? 

Tron 1982

Monday, November 26, 2012

Zend Framework 1: Zend Form Display Groups

Greetings Programs,

Creating large forms with many inputs can be a challenge for your UI especially if you want to avoid scrolling the page. These days with tablets, smart tvs, and cell phones the need to create UIs that minimize scrolling is often desired. If you and your team are going to write an app for every platform out there then you probably have a pretty big team. If you don't,  don't despair, many of these platforms have a browser so if you're careful how you design your UI you might find that you can have a very nice interface across many platforms and not have to have a fleet of developers for every platform out there. 

Zend Forms and display groups are one potential way to solve this problem. In this Post we are going to create a shipping and billing address form that is split across the screen. Billing on one side and shipping on the other. We will be using form decorators to wrap display groups in a div that can be positioned using CSS. In the next post we will look at using sub forms to accomplish the same effect.

The code is available at https://github.com/jdellostritto/ZTMPL_formdisplaygroups.git


To start we need an idea of what we want this to look like...


The form above is separated in two halves based on our target design. A sample structure that will allow for what we want to accomplish can be seen below.

...
Full code for the Application_Address_Form Class can be found on github. In this form class we create functions for the inputs we need created. Because we have two nearly identical display groups we create a single function that creates our input text field based on a name we give it.  In the _render_fullname function we send an argument called $given_name. Calling $this->_render_fullname("bill_fullname") and $this->_render_fullname("ship_fullname") will result in two input elements on our form (we could further optimize our code by creating a single function that creates any text input - later). All we need to do after this is add them to two distinct display groups....

The init() function of our form helps us do just this. First we create the items we need in our form. Notice step 4 where we create duplicate inputs for both groups:
...
Second we create our groups and decorate the form. Step 7 in the code below is where we create our display groups giving the names of the elements created previously as an array, giving each group a distinct name, and finally decorating them in a structure that meets our design requirements.
...
Decorating our groups is done in the function below. Notice that we take the group name and a given_name as arguments. The group is the target display group and the given_name is a string we can use to differentiate our div id attribute:
...
The last item left on our list is to style our page to get the desired effect. This is accomplished by absolute positioning the bill group and ship group....


I have some other small tricks in this baseline that I have learned from many sources... too many to list.  There are many ways to accomplish what i have posted so please if you find the time to contribute to this code or make suggestions please do not hesitate. I have learned from many posts and other sources and I appreciate every one.  

...
Kevin Flynn: Like a man says, "There are no problems, only solutions."
...
Tron 1982

Friday, November 9, 2012

Zend Framework 1 - Zend Form Custom Error Handling

Greetings Programs!
Zend Forms... a black art?

At first it may seem but spend some time and you just might realize how powerful they are. Over the past two years I have been working with the Zend framework and have become very fond of it. It is not overly prescriptive and allows me to exercise pattern design extending it and bending it to my will. I will admit that early on zend form decorators was a major challenge. It wasn't until design and front end requirements really pushed me to see how far I could extend zend forms. After a number of big challenges I realized there's a lot you can do with zend forms and decorators.

In this blog we are going to look at a Zend form and how we control error display. In a nutshell we want to....
1: Show only a "*" next to fields that have errors. 
2: Show only one error in an error field <div> based on priority.
3: decorate the form in a <div> structure.

The real problem we are trying to solve is the potential endless diarrhea of errors that can spill out of the form onto our UI and just mess everything up. 
Code can be found here: https://github.com/jdellostritto/ZTMPL_formerrors.git

So here is what we want to see in this very simple registration form.


You will notice that the email format is incorrect above. The error message tells the user and is our first priority message. Note: the password fields are incorrect (empty) as well and the form indicates that however, we don't spill those errors messages out all over the screen.

Here is a submission with a correct email format:

Notice that the email is correct and we only see the required field error because I failed to put in either the password or the confirm password. Next I will enter a password in the password field that is too short so I expect to see a length failure.


As you can see we are walking through the process one input at time. We are not leaving the user with out cues for the fields that are invalid however, we are controlling the mess that could ensue especially if we have a form with a lot of fields and many errors.  This allows us to keep our UI 'Crispy' (ref: Crispy is term used by a front end designer I know his name is Kalim).

WHAT DECORATORS DO WE NEED TO PULL THIS OFF.

Below is the HTML structure we want to use to make this work. You should always start with a definition of you ideal structure. Don't be afraid of how complex it might look. I haven't encountered a structure I couldn't resolve with decorators and zend forms.
<form>
   
   <div class="input">
   <input type="text" name="emailaddress" id="emailaddress" value="" placewholder="email address">
   <div id="error_condition_input">zend element <ul> error</div>
   </div>

   <div class="input">
   <input type="password" name="password" id="password" value="" placeholder="choose a password">
   <div id="error_condition_input">zend element <ul> error</div>
   </div>

   <div class="input">


   <input type="password" name="confirmpassword" id="confirmpassword" value=""  placeholder="confirm password">
   <div id="error_condition_input">zend element <ul> error</div>
   </div>

   <div class="submit">
   <input type="image" name="submit_reg" id="submit"    src="/zendformsample1/public/media/img/forms/next.png" type="image">
   </div>

</form>
<div id="error_condition_form">zend form <ul> custom error</div>   

First: Notice that each input has it's own <div id="error_condition_input"><div>. This is were the "*" asterisk will show up when the input is invalidated. 

Second: notice the <div id="error_condition_form"></div> at the end after the form. This is were we will show the custom error based on a priority that we set.

DECORATING THE TOP LEVEL FORM. 
I choose to decorate the form in stages. I start simply start by calling a function in my form class to do just that (function can be found in Application_Form_Index_Register Class on github).The setDecorators function is called on the form to create our default structure. Notice that we wrap our errors in the div based on the HTML structure we defined earlier. ...
DECORATING THE INPUT BOX
In the code below we define a function that will allow us to decorate our input boxes. The code above should look familiar. Wrapping the error generated by the input is accomplished the same way it was accomplished at the form level. We then wrap the whole thing in a <div> in the last line. ...

DECORATING THE SUBMIT BUTTON IMAGE
We only have a single submit button so we decorate it when we create it. If we have more than one it would make sense to move this function out into a separate function.In the _render_submit()function setDecorators is called on the submit button wrapping it in a <div> with a class = "submit".

...


TEST FOR ERRORS
At this point we should be all 'decorated up'. Each input has a nice div element for errors as does our form. With a little CSS we can move things around and have a nice looking form (see sample CSS on github). Below you will find the code for processing and setting the errors.  ...
The code above grabs the form errors which contains a listing of all the errors from each input in the order the input presents itself on the page. Using this ordering we prioritize the capture of the error and use the setErrors function for the form which overwrites any previously set error messages and flags a failed validation. It will then return. Remember the individual input errors are preserved and each is set to display "*". For more information on how this is done you'll need to look at the class Application_Form_Index_Register and the validators that are used for each input box. Again these are available on github. 

I have some other small tricks in this baseline on github that I have learned from many sources... too many to list (css helpers, resource loading, etc.). I am also aware that there are alternate approaches and some may be more clever than mine. I am happy to learn so please comment and suggest.

...You've enjoyed all the power you've been given, haven't you. I wonder how you'd take to working in a pocket calculator...
...
End of line

Master Control Program: Tron 1982