The Power of Zend_Validate and Zend_Filter

 Development, Zend Framework  Comments Off on The Power of Zend_Validate and Zend_Filter
Sep 062011
 

I don’t know about you, but I find that sometimes coding html forms and the corresponding backend validation to be the typical type of “Boiler Plate” code that once you’ve done it and understand the principles, that you never really want to have to do it again.

Into the breach steps Zend_Frameworks’ Zend_Validate and also Zend_Filter. This set of classes can be used in conjunction with the Zend_Form_Element Classes and Zend_Form Class and makes validating forms almost a pleasure. Let me show you an example.

Often with a web form we need to validate that an email address is valid. So you might use a function such as:

filter_var($email, FILTER_VALIDATE_EMAIL)

And then redirect back with an error stored in the user’s session if it fails. However it gets a little more tricky when you also need to validate that the email address is unique to your database table.

public function validateUsersEmail(){
if(filter_var($this->email, FILTER_VALIDATE_EMAIL)){
//do query to check email address not already entered
//if no return true
}
return false;
}

However Zend Framework offers a set of very powerful filters. which means you can create a form email like so from within a class extending Zend_Form:


$handleElement = new Zend_Form_Element_Text("handle");
//Here is where the validator kicks in
$handDbValidator = new Zend_Validate_Db_NoRecordExists('siteusers','handle');
$handDbValidator->setMessage("That username already exists");
$handleElement->setLabel("Username")
->setRequired(TRUE)
->addValidator("NotEmpty",TRUE)
->addFilter(new Zend_Filter_Alnum(false))
->addFilter(new Zend_Filter_StripTags())
->addValidator($handDbValidator)
->addFilter(new Zend_Filter_StringTrim());
->setOptions(array("size"=>"35","maxlength"=>"10","class"=>"textinput",
"placeholder"=>"Username"))

Now that looks like a lot of code. However there are several validators and also filters being applied to this element.

Here is the code for checking if a record exists and also to set the error message to report to the user

$handDbValidator = new Zend_Validate_Db_NoRecordExists('siteusers','handle');
$handDbValidator->setMessage("That username already exists");

Here we specify the table name and the field name to check and then add an error message if it fails.

Now the filters

So how often have you gone searching for the right regular expression to strip out all none alpha numeric characters from a string? Well I know I often forget the exact syntax and go searching. Zend Framework offers you a great set of Filters to apply to your form elements. In the above code you can see them at work in the following way:

->addFilter(new Zend_Filter_Alnum(false))
->addFilter(new Zend_Filter_StripTags())

These are fairly self explanatory but show what is possible using the Zend_Form Class along with filters and validators.

You can find out more on validators and also Filters by following the links.

creating a request filter – allowing for /username

 Development, Zend Framework  Comments Off on creating a request filter – allowing for /username
Aug 302011
 

Often in modern websites, particularly social websites, the urls are in the format of http://somesite.com/username. This presents something of a problem for web apps that follow the MVC pattern and direct all requests through a single front controller that then dispatches the request to the correct controller based on the url or on a route set up in the app. Recently I have begun work on a website, groups.ie and I wanted to implement a url pattern of http://groups.ie/the-group-name . So how so we achieve this when we cannot properly map this using a route as the group name could be almost anything?
I achieve this by using a simple Zend plugin. Here is the code:

/**
* Description of GroupFilter
* allows for urls to follow the format of
* sitename/group-name
*
* @author craigbrookes
*/
class Application_Plugin_GroupFilter extends Zend_Controller_Plugin_Abstract {

public function preDispatch(Zend_Controller_Request_Abstract $request) {
$controller = $request->getControllerName();
$groupMapper = new Application_Model_GroupsMapper();
$group = $groupMapper->findRowByFieldsAndValues(array("url"=>$controller));

if(!$group->isEmpty()){

$request->setControllerName("group");
}
}

}

So in this code, I extend the Zend_Controller_Plugin_Abstract which provides several hook functions (functions which the parent or a controller will call on all plugins at certain times during execution)

The hook functions provided are:

  • routeStartup(): prior to routing the request
  • routeShutdown(): after routing the request
  • dispatchLoopStartup(): prior to entering the dispatch loop
  • preDispatch(): prior to dispatching an individual action
  • postDispatch(): after dispatching an individual action
  • dispatchLoopShutdown(): after completing the dispatch loop

In the above code I choose only to implement the preDispatch() which is past the instance of
Zend_Controller_Request_Abstract. From this request object I get the current controller which my be set to the name of a group. I then use my Mapper class and check if there is a group that responds to the controller name. Finally, if there is a group object found, then I set the controller to the Groups controller which can then take over. Other wise the request continues along its merry way. Got any other solutions or can see potential problems with my solution, please leave a comment and let me know.

For more information on plugins, I found this article to be quite useful.

Abstract Zend Data Mapper Class for Zend Framework

 Development, Zend Framework  Comments Off on Abstract Zend Data Mapper Class for Zend Framework
Aug 232011
 

I have started a new project with a fellow programmer, Peter Fortune @pfortune. The project is a group organising tool, aimed at the Irish market and will be hosted under the domain http://groups.ie.

So when discussing this project, we decided to use Zend Framework as we both are very comfortable with PHP and I have used Zend Framework in the past. After working on the design of the database schema, it came to laying the ground work for the project. Building the models fell under my todo list and so I set to work.

So I spent a little time coming up with what I think is a reasonable Abstract class for the Applications data mapping classes to extend. I know quite a few developers prefer to use doctrine with Zend Framework, and when the project progresses, this may be something we will consider using also, but for the time being, I went with the inbuilt tools Zend_Db_Table_Abstract etc. So here is the class I ended up with. Please give me your thoughts and criticisms and point out any gaping errors.


setDbTable($tableName);
$this->_model = $model;

}

public function setDbTable($dbTable)
{
if (is_string($dbTable)) {
$dbTable = new $dbTable();
}
if (!$dbTable instanceof Zend_Db_Table_Abstract) {
throw new Exception('you must pass a class that extends Zend_Db_Table_Abstract');
}
$this->_dbTable = $dbTable;
return $this;
}

/**
*
* @return Zend_Db_Table_Abstract
* return concrete child
*/
public function getDbTable()
{
if (null === $this->_dbTable) {
throw new Exception("no dbtable set");
}

return $this->_dbTable;
}

/**
*
* @param Application_Model_RowAbstract $row
* @return array
* returns an array of concrete children extending Application_Model_RowAbstract
*/
public function findAllByExample(Application_Model_RowAbstract $row)
{
//returns all public properties and their values in assoc array
$props = get_object_vars($row);
$sql = $this->getDbTable()->select();
foreach($props as $property=>$value){
if(!NULL == $value)
$sql->where(''.$property.' = ?',$value);
}

$rows = $sql->query()->fetchAll();
$ret = array();
foreach($rows as $row){
$ret[]= new $this->_model($row);
}
return $ret;

}

/**
*
* @param Application_Model_RowAbstract $row
* @return Application_Model_RowAbstract
* returns a concrete child
*/
public function findRowByExample(Application_Model_RowAbstract $row){
$props = get_object_vars($row);
$sql = $this->getDbTable()->select();
foreach($props as $property=>$value){
if(! NULL == $value)
$sql->where(''.$property.' = ?',$value);
}

$sql->limit(1);
$rows = $sql->query()->fetchObject($this->_model);
return $rows;
}

/**
*
* @param Application_Model_RowAbstract $row
*
* chooses to save or update based on whether the primary key is set or not
*/
public function saveUpdate(Application_Model_RowAbstract $row)
{
//get pri key from get_primary() public method added
//to concrete implimentation of Zend_Db_Table_Abstract
$prikey = $this->getDbTable()->get_primary();
$prikey = $prikey[1];
$data = get_object_vars($row);
if(isset($row->$prikey)){
//update
$updateData = array();
foreach($data as $property=>$value){
if(!NULL == $value)
$updateData[$property]=$value;
}
print_r($updateData);
//$this->getDbTable()->update($updateData, ''.$prikey.'='.$row->$prikey.'');
}else{
//insert
$this->getDbTable()->insert($data);
}

}

/**
*
* @param mixed $value
* @return Application_Model_RowAbstract
* the value is the value of the primary key set for the row
*/
public function findWherePriKeyEquals($value){

$row = $this->getDbTable()->find($value);
$ret = $row->current();
return new $this->_model($ret->toArray());

}

}

so that’s it. As you can see you have most functionality there. You can create a dummy object and find all that match its values in the database. You can update and save an objects values
and you can find based on simple rules. All of this means that the concrete sub classes have a lot less work to do. Hope this is helpful.

© 2012 Craig Brookes Suffusion theme by Sayontan Sinha