Generic Data save with Zend Framework

This technical article hilights one the famous ideal goal we all want to achieve : scaffolding, CRUD, BREAD, call it what you want, all we want is to get rid of repetitive sql query writing.  Zend framework provides powerful data abstraction  and here are a few tips to use Zend_DB_Table to its best. Of course this article assumes you have an idea of MVC development with Zend Framework.

Why are we doing this ? in the course of writing ajax actions, we needed our controller to react to any POST provided by specific forms : whatever the fields in the form, we want them to be saved to our table. Code below is a specific implementation of a controller that responds to specific ajax queries. Please bear in mind that it is only provided as an example of generic query action. Other portions of code are not optimal, such as viewless actions in the renderAjax method, not the best.

[update 20090428] Alternative :  Smart save on Zend_Db_Table objects from zfsnippets

Controller Implementation

Our controller is a simple Zend_Controller_Action. We load the database model at init time, and specify the primary key  (node parameter) in a class variable. Note that our data model is also stored in a class variable.

class UserController extends Zend_Controller_Action
{
public function init()
    {
        $this->session = new Zend_Session_Namespace('User');
      //  $this->view->translate = Zend_Registry::get('Zend_Translate');
	  	require_once 'models/Users.php';
		$this->data=new Users();
		$this->node = $this->getRequest()->getParam(node);
		WXC_Log::log("init node : " . $this->node);
    }

Quick look at the model

at this stage I specify on particular function I like to implement in Zend Framework Models : the primary key ! Other functions of the model could include add, delete and update : we'll see below that our generic data admin prefers to do the job in the controller.

class Users extends Zend_Db_Table_Abstract
{
    protected $_name = 'users';
 	public function primaryKey()
	{
		$info = $this->info();
		return $info[primary][1];
	}
}

Back to the crontroller : the renderAjax method is a quick one that stops the view from being rendered. If you are a specialist of Zend Framework you will notice that this can be better performed with the contextSwitch action helper. Use the code below only for testing, for production you'd rather spend a few minutes learning about helpers !

		private function renderAjax()
{
		$this->_helper->layout->disableLayout();
		 $this->_helper->viewRenderer->setNoRender();
}

Action !

Listing records is the first thing you want to look for when working at data scaffolding. the code below reads metadata from the table, lists all columns from your table, fetches data and returns them as JSON (ready for extjs grid display, by the way).

 public function listAction()
{
	 $this->renderAjax();

	  if (null === $select)    $select = $this->data->select();

      $thRowSet = $this->data->fetchAll( $this->data->select());

	$nodes=array();
	 $arrMeta=$this->data->info();
		$arrCols=$arrMeta[cols];

foreach($thRowSet as $row ){
	$arr_node=array();
foreach ($arrCols as  $v)
	$arr_node[$v]=$row->$v;

	$nodes[]=$arr_node;
}

	echo Zend_Json::encode( $nodes );
}

The next step would be to add records : we have not worked on this yet so you'll want to try this with tables that have a few records in them. The method below works with two types of data sets.

  1. Multiple column form submit :this would be the classical response to a from submission, where each field bears the NAME of the database field, and obvisouly the value is the data. Such forms are transmitted via FORM array with key / value pairs. We read the POST (getRequest->getParam) that match metadata built from the database table column array. We then provide a clean arrData array of new data for the update() method of our Zend_Db_Table instanciation. This method takes two arguments: the first is the associative array mapping columns to change to new values to assign to these columns. The second is the where clause that we built from the primary key
  2. Single column submit : the technique is useful when working with extjs in place editing, where one piece of code can edit multiple fields. The field variable contains the database column name and the value is the data. We add a check that matches the field against database table column names
public function saveAction()
{
	$this->renderAjax();
$id= $this->node;
 $key = $this->data->primaryKey();
$strWhere = $key. '='  . $id;

 $arrMeta=$this->data->info();

// all columns submit
$arrCols=$arrMeta[cols];
$arrData=array();
reset($arrCols);
while (list($k,$v)=each($arrCols))
	{
		 if ($v!="parent_id"  && $v!= $this->data->primaryKey()
		  && array_key_exists($v, $this->getRequest()->getParams()))
		 {
			$arrData[$v]=$this->getRequest()->getParam($v);

			}
	}

//single column submit via field/ value
if ($this->getRequest()->getParam('field')!="")
{$field = $this->getRequest()->getParam('field');
$value= $this->getRequest()->getParam('value');
$arrData[$field] =$value;

}

  if (is_array($arrData))
	{
	  try{      $this->data->update($arrData,$strWhere);
	 echo 1;}
	  catch(Zend_Exception $e){  echo 0;}

	}
else echo 0;

}

A good start for extjs development : Hope this is useful for you !!

0 replies

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply

Your email address will not be published. Required fields are marked *