Zend_Db_Table_Select Dynamic Finder
Hello, Habr! 
Wrote a class that uses Zend_Db_Table_Select and allows you to use a Dynamic Finder in the models in projects based on Zend Framework. An article about the fact that this class is able to, as well as the link to the source code is offered to your attention.
Dynamic Finder method to retrieve data from a database table, recording the names of the required fields in the name of the class method, and the values of these fields as a method argument. For example, can be used in the instance of the model class associated with any database table.
Dynamic Finder allows you to avoid writing of a number of methods of the form getById(...), getByLoginAndPassword(...), getAllByCountry(...) inside the model in the form of building a full-fledged SQL queries and samples. Instead, in this implementation, it is sufficient to connect a Dynamic Finder to the model properly, then the programmer can use these methods directly in the controller or view. In fact these methods in the model do not exist.
Thus, saving time of work of the programmer.
Dynamic Finder has already been implemented in some form or other in various libraries and frameworks, particularly Ruby on Rails.
In this implementation, the Dynamic Finder is an add-in using Zend_Db_Select / Zend_Db_Table_Select, determined for samples from only one table.
Used several types of syntax. The simplest:
getBy... identical getAllBy... – i.e. means a query with many rows. To retrieve only one row you can use getOneBy...
The syntax of the names of the requested fields used in the name of the method is the recording of the names of these fields in CamelCase – mode. In this case the field named user_name must be recorded in the method name as a UserName (each word beginning with an underscore, is replaced by a word with a capital letter). Different fields in the name of "virtual method" logical operators And or or.
For example,
The syntax of the argument "virtual method" supports two forms: a short (as arguments separated by commas recording the values of the fields on which to build a query, see the examples above) and complete. The full form requires the argument to this method an associative array and looks in its most General form like this:
The writing order of the field values (array of values or a simple case) must match the order of field names in the title "virtual method". Array of options containing key and value are optional, but are there for them and any default values. As arguments you can use instances of class Zend_Db_Expr:
In my opinion, the easiest way is the class object Dynamic Finder to have in the model as private – property:
Primary processing "virtual method"; retrieving data from the database after generation of the desired Zend_Db_Table_Select:
$this->getTable() should return associated with the model Zend_Db_Table object.
In principle, everything could be completely different. For example, you can feed DymanicFinder as a select in some way pre-prepared instance of Zend_Db_Table_Select (Zend_Db_Select) that meet exactly your specific task. Also, another way you can pass and array-list of available fields in the table. Similarly, different can be processed and the results of the conversion of the Zend_Db_Select object() (instead of the terms validation getOneBy). For the sake of the possible, the desired end-programmer improvements, Dynamic Finder in this case and is made in the form of such "prefabricated". For all sorts of customization.
There is also the option of an external parsed the method name (instead of the internal _camelCase2underscore() ). Ie your naming columns in tables and the names of the methods for finder will be different. In this case, somewhere before you call the method __call is necessary to define the property $this->columnParseCallback in the form of callback (like call_user_func()), in which you specify an external function is a parser for your method name.
And inside we have php code that won't work if he doesn't pass no heir Zend_Db_Table_Select (Zend_Db_Select enough and if used, for example, with a single table) or a list of valid fields. And then who knows what afterwards the programmer when writing a virtual method uchudil? ;)
Class source code is available at the link.
UPD: a Bug with line 337 fixed, as little popravljeno formatting. Thanks to dmitry_dvp
Article based on information from habrahabr.ru

Wrote a class that uses Zend_Db_Table_Select and allows you to use a Dynamic Finder in the models in projects based on Zend Framework. An article about the fact that this class is able to, as well as the link to the source code is offered to your attention.
What's that for?
Dynamic Finder method to retrieve data from a database table, recording the names of the required fields in the name of the class method, and the values of these fields as a method argument. For example, can be used in the instance of the model class associated with any database table.
Dynamic Finder allows you to avoid writing of a number of methods of the form getById(...), getByLoginAndPassword(...), getAllByCountry(...) inside the model in the form of building a full-fledged SQL queries and samples. Instead, in this implementation, it is sufficient to connect a Dynamic Finder to the model properly, then the programmer can use these methods directly in the controller or view. In fact these methods in the model do not exist.
Thus, saving time of work of the programmer.
Dynamic Finder has already been implemented in some form or other in various libraries and frameworks, particularly Ruby on Rails.
In this implementation, the Dynamic Finder is an add-in using Zend_Db_Select / Zend_Db_Table_Select, determined for samples from only one table.
How to use this?
Used several types of syntax. The simplest:
$modelObj->getByTag($tag);
getBy... identical getAllBy... – i.e. means a query with many rows. To retrieve only one row you can use getOneBy...
The syntax of the names of the requested fields used in the name of the method is the recording of the names of these fields in CamelCase – mode. In this case the field named user_name must be recorded in the method name as a UserName (each word beginning with an underscore, is replaced by a word with a capital letter). Different fields in the name of "virtual method" logical operators And or or.
For example,
$user->getOneByLoginAndPassword($login, $password);
The syntax of the argument "virtual method" supports two forms: a short (as arguments separated by commas recording the values of the fields on which to build a query, see the examples above) and complete. The full form requires the argument to this method an associative array and looks in its most General form like this:
$data = $files->getAllByPaperId(
array('values'=>array($paperId, ...),
'options'=>array(
'order'=>array('orig_filename ASC'),
'offset' => $offset,
'limit' => 10
) ) );
The writing order of the field values (array of values or a simple case) must match the order of field names in the title "virtual method". Array of options containing key and value are optional, but are there for them and any default values. As arguments you can use instances of class Zend_Db_Expr:
$data = $tagObj->getAllByTag(new Zend_Db_Expr(sprintf(" LIKE '%s%%'" , $beginStr)));
Connecting to the model.
In my opinion, the easiest way is the class object Dynamic Finder to have in the model as private – property:
/**
* Dynamic Finder object
* @var DynamicFinder
*/
private $_dynFinder;
public function __construct() {
if (!class_exists('DynamicFinder',false)) {
require_once 'path_to'. '/DynamicFinder.php';
}
$this->_dynFinder = new DynamicFinder();
}
Primary processing "virtual method"; retrieving data from the database after generation of the desired Zend_Db_Table_Select:
public function __call($name, $arguments)
{
$this->_dynFinder->select = $this->getTable()->select();
$this->_dynFinder->allowedFields = $this->getTable()->info(Zend_Db_Table_Abstract::COLS);
$select = call_user_func_array(array($this->_dynFinder, $name), $arguments);
if (strpos($name,'getOneBy')===0){
return $this->getTable()->fetchRow($select);
} else {
return $this->getTable()->fetchAll($select);
}
}
$this->getTable() should return associated with the model Zend_Db_Table object.
In principle, everything could be completely different. For example, you can feed DymanicFinder as a select in some way pre-prepared instance of Zend_Db_Table_Select (Zend_Db_Select) that meet exactly your specific task. Also, another way you can pass and array-list of available fields in the table. Similarly, different can be processed and the results of the conversion of the Zend_Db_Select object() (instead of the terms validation getOneBy). For the sake of the possible, the desired end-programmer improvements, Dynamic Finder in this case and is made in the form of such "prefabricated". For all sorts of customization.
There is also the option of an external parsed the method name (instead of the internal _camelCase2underscore() ). Ie your naming columns in tables and the names of the methods for finder will be different. In this case, somewhere before you call the method __call is necessary to define the property $this->columnParseCallback in the form of callback (like call_user_func()), in which you specify an external function is a parser for your method name.
Implementation.
And inside we have php code that won't work if he doesn't pass no heir Zend_Db_Table_Select (Zend_Db_Select enough and if used, for example, with a single table) or a list of valid fields. And then who knows what afterwards the programmer when writing a virtual method uchudil? ;)
Class source code is available at the link.
UPD: a Bug with line 337 fixed, as little popravljeno formatting. Thanks to dmitry_dvp
Комментарии
Отправить комментарий