📜 ⬆️ ⬇️

Database abstraction

When I first started writing in PHP, I owned OOP, perhaps, at the syntax level, no more. At that time, I had quite enough mysql_ * functions. Over time, the experience became more, I began to think about optimization. This topic describes the evolution of my code.

The first step was to write a simple class, which facilitated the work with the database. The code was not much less, mostly standardized queries were simplified. Also, input parameters were automatically shielded. Bonus, the opportunity to use the code from a database other than MySQL (writing class with the same interface). At least, most of the requests would not have to be rewritten. The code looked like this:
$ db = new MysqlDb ($ server, $ user, $ pass, $ db, $ prefix);
$ db-> select ($ key, $ value ); // Perhaps there were many query options using a different number of parameters.
while ($ db-> fetch ()) {
$ row = $ db-> getRow ();
...
}
Or $ rows = $ db-> getResult ();
* This source code was highlighted with Source Code Highlighter .

To further simplify work with the database, I began to use Active Record. My decision was largely lost by outsiders, but then I missed it. The Zend Framework appeared at that time, so some ideas are taken from it. The classes themselves worked through PDO (although there was also a library for working through php_mysql).
Code example:
$ db = Cms_Db :: factory ( 'MySQL' );
$ db-> connect ($ server, $ user, $ pass, $ db, $ prefix);
$ element = $ db-> select ( 'id' , $ id);
$ element-> name = 'New name' ;
$ element-> update (); * This source code was highlighted with Source Code Highlighter .

This option lived for a long time. But over time, and he was missed. The class was developed extensively, new methods were added for processing standard queries. By the time the stable release of the Zend Framework was released. It has become annoying to constantly add new types of queries.

Over time, I began to write models for the main site objects. Inside, my old class was still working, but outside, all operations looked pretty transparent. I liked this approach, and to simplify the implementation, I decided to use ORM. At first, I looked closely at Doctrine and Propel, but in the end I decided to write my own implementation.

Working with the database is done via Zend_Db, Zend_Db_Select is also used for flexibility. The model description is a lot like Doctrine. But my model also contains data intended to describe the presentation of some data. I will give an example:
class Model_News extends Cms_Essence_Model
{
public function setDefinition ()
{
$ this -> addField ( 'name' , 'Title' )
-> addField ( 'link' , 'Address' , 'link' )
-> addField ( 'date' , 'Publication date' , 'date' )
-> addField ( 'description' , 'Short description' , 'text, 255' , array (
'validate' => 'isVoid' ,
'detail' => true
))
-> addField ( 'content' , 'Content' , 'editor' , array (
'detail' => true
'minLength' => 40,
'validate' => array ( 'isVoid' , 'minLength' ))
))
-> setOption ( 'editorTableClass' , 'newsTable' );
}
}
$ element = Cms_Essence :: get ( 'Model_News' ) -> getById (2); * This source code was highlighted with Source Code Highlighter .

As in the full ORM, you can also describe the connection table and use code like:
$ user = Cms_Essence :: get ( 'Model_User' ) -> getJoined ( 'Model_Group' , 'name' , 'megahertz');
$ groupName = $ user-> group-> name; * This source code was highlighted with Source Code Highlighter .

Of course, for the convenience of such requests, I am still far from a full ORM, but so far this option suits me.
')
This approach allows you to write a minimum of code. Having the model described, I can use it in the admin panel without writing a single line of code. Moreover, the admin panel can be any type, classical, ajax editor on the site, via RPC on another site, etc. You can also use components in the templates so as not to write code. For example, on the Smarty component will look like this:
{state model = Model_News name = news limit = 3}
< ul >
{list from = $ news}
< p >
< b > {$ newsList- > name} {$ newsList- > date} </ b > <br />
{$ newsList- > description} <br />
<a href = "{$ newsList-> getUrl ()}" > more </ a >
</ p >
{/ list}
* This source code was highlighted with Source Code Highlighter .

Another significant advantage of this model is that it is possible to automatically cache the result of the samples. Any sample is cached, and during operations of changing the model data, the cache is automatically cleared.

In the future, I do not exclude the possibility of maintaining this approach, but based on Doctrine. But so far there is no need. I think this is not the last version of abstraction.

Source: https://habr.com/ru/post/30659/


All Articles