ORM технология
Уроки ORM технология
29 октября 2013
2344
ORM технология, ORM, PDO

ORM технология

Сложность Рубрика PHP
Демонстрация » Скачать »

Здравствуйте! В этом уроке я покажу несложный пример реализации ORM технологии. Для тех, кто не в курсе, что такое ORM вот Вам цитата с википедии: «ORM (англ. Object-relational mapping, рус. Объектно-реляционное отображение) — технология программирования, которая связывает базы данных с концепциями объектно-ориентированных языков программирования». Чтобы было яснее приведу пример ее использования пока что,  не затрагивая ее реализацию, но для начала поговорим о том, какие php-«инструменты» я использовал для работы с базой данных.

 

В PHP есть встроенный класс предоставляющий доступ к серверу данных – PDO. Почему я использовал его, а не стандартные функции по работе с СУБД MySQL? На то есть две причины: во-первых в PDO изначально встроены решения по проверке данных на вредоносность, которые выполняются автоматически, а во-вторых класс PDO позволяет работать с разными СУБД, что делает систему еще более гибкой. Ниже приведен код с настройками подключения к серверу баз данных.

 

class PDOConfig extends PDO {

 

private $engine;

private $host;

private $database;

private $user;

private $pass;

 

public function __construct(){

$this->engine = 'mysql';

$this->host = 'localhost';

$this->database = 'dbname';

$this->user = 'root';

$this->pass = '';

$dns = $this->engine.':dbname='.$this->database.";host=".$this->host;

parent::__construct( $dns, $this->user, $this->pass );

}

}

 

 

Используя данный класс можно получить доступ к серверу БД всего на всего создав его экземпляр. Теперь я покажу Вам, как просто работать с базой данных, используя ORM технологию.

Для примера возьмем таблицу, которая содержит новости сайта и заключает в себе заголовок, дату, непосредственно текст новости.

 

// подключаемся к серверу бд

$pdo = new PDOConfig();

 

//создаем экземпляр класса для работы с таблицей

$news = new News($pdo);

 

//далее присваиваем значения полям таблицы

$news->title = ‘Заголовок новости’;

$news->date = ‘0000-00-00’;

$news->content = ‘Содержимое новости’;

 

//сохраняем запись в таблицу

$news->save();

 

// удаление первой новости датированной числом – 29.10.2013

$news1 = News::findFirst(array(‘date’ => ‘2013-10-29’));

$news1->delete();

 

Как Вы могли заметить, в коде, приведенном выше нет ни одного запроса, все сводиться к простейшему присваиванию и вызову методов. Вот теперь, наконец, я объясню Вам, как можно достичь такой простоты работы с сервером БД. Все сводиться к одному классу, реализующему в своих методах основные действия и автоматизирующему выполнения запросов к базе данных. В этом классе содержаться следующие атрибуты:

 

//подключение к бд

protected $pdo;

//название таблицы для выполнения запроса

protected $table = '';

 

protected static $tableName = '';

//массив с полями таблицы и их значениями

public $attributes = array();

//список полей таблицы

public $fieldsList = array();

 

 

Благодаря функциям __set и __get в php можно перехватить событие обращения к данным класса. По средствам этих функций, в нашем  ORM классе происходит запись данных в массив $attributes и получение этих данных. Код этих функций проиллюстрирован ниже.

 

public function __set($name, $value)

{

         //Если название поля таблицы есть в списке,

//то записываем полученные данные

         foreach($this->fieldsList as $field)

         {

                  if($field == $name)

                  {

                            $this->attributes[$name] = $value;

                   }

         }

}

 

public function __get($name)

{

         //Возвращаем значение при

//условии его существования

if(isset($this->attributes[$name]))

         {

                  return $this->attributes[$name];

         }

}

 

Далее функции удаления и записи данных в БД:

 

public function delete()

{

         $sth = $this->pdo->prepare('DELETE FROM '

.$this->table.' WHERE id=:id');

         $sth->execute(array('id'=>$this->id));

}

 

public function save()

{

         /*Если запись новая,

то ей еще не присвоен id.

Это означает, что мы ее «вставляем»

В таблицу, а иначе обновляем данные

в уже существующей записи */

         if($this->id == '')

         {

                   $this->insert();

         }

         else

         {

                  $this->update();

         }

}

 

 

При сохранении данных вызывается одна из функций изображенных ниже.

public function insert()

{

  $fields='';

  $values='';


// формируем строку запроса

// из списка полей таблицы

$i = 1;

foreach($this->attributes as $key=>$value)

  {

           $fields.=$key;     

           $values.=':'.$key;

 

           if($i$this->attributes))

           {

                     $fields.=', ';

                     $values.=', ';

           }

 

           $i++;

  }

 

  $query='INSERT INTO '.$this->table

.' ('.$fields.') VALUES ('.$values.')';

 

  $sth = $this->pdo->prepare($query);

  $sth->execute($this->attributes);

 

// записываем присвоенный id,

// после чего запись не считается

// новой при сохранении

  $this->id=$this->pdo->lastInsertId();      

}

 

public function update()

{

  $fields='';

 

  $i = 1;

  foreach($this->attributes as $key=>$value)

  {

           if($key!='id')$fields.=$key.'=:'.$key;        

 

           if($i$this->attributes) && $key!='id')

           {

                    $fields.=', ';

           }

           $i++;

  }

  $query='UPDATE '.$this->table

.' SET '.$fields.' WHERE id=:id';

 

$sth = $this->pdo->prepare($query);        

$sth->execute($this->attributes);

}

 

 

Теперь две статические функции поиска, одна из которых возвращает только первую найденную запись, а вторая массив всех записей.

 

public static function findFirst($param = array())

{

$class = get_called_class();

         $table = $class::$tableName;



         $query = "SELECT * FROM ".$table;

         if(count($param) > 0)

         {
                   $where = ' WHERE ';
                   $i = 0;
                   foreach($param as $key=>$value)

                   {
                            $where .= ($i == 0)?' ':' AND ';
                            $where .= $key.' = :'.$key;
                          $i++;
                   }
                   $query .= $where;
         }

         $pdo = new PDOConfig();
         $obj = new $class($pdo);
         echo $query.'';
         $sth = $pdo->prepare($query);
         $sth->setFetchMode(PDO::FETCH_INTO, $obj);


         $sth->execute($param);                  

foreach ($sth as $a) {
                   $obj = $a;
                   return $obj;
         }
}

 

public static function find($params = array())
{
  $class = get_called_class();
  $table = $class::$tableName;
 

  $query = "SELECT * FROM ".$table;

  if(isset($params['where']))
  {
           $where = ' WHERE ';
           $i = 0;

           foreach($params['where'] as $key=>$value)
           {
                     $where .= ($i == 0)?' ':' AND ';
                     $where .= $key.' = :'.$key;
                     $i++;
           }
           $query .= $where;
  }

 

  if(isset($params['condition']))

  {

           $query .= ' '.$params['condition'];

  }
  $pdo = new PDOConfig();

  $sth = $pdo->prepare($query);

  $sth->setFetchMode(PDO::FETCH_CLASS, $class, array($pdo));

  $sth->execute((isset($params['where']))?$params['where']:null);

  $result=array();

  while($obj = $sth->fetch())

  { 
            $result[]=$obj;
  }
  return $result;
}

 

 

Теперь можем приступить к написанию класса для работы с конкретной таблицей. Этот класс единственное, что придется писать разработчику для работы с базой данных при условии, что у него есть ORM библиотека. За примером не будем далеко ходить и просто напишем класс для работы с таблицей news, который экземпляр которого уже использовали в примере в начале урока.

 

class News extends MyORM {
         protected $table = 'news';
         protected static $tableName = 'news';
         public $fieldsList = array('id', 'title', ‘date’, ‘content’);
}

 

 

Обратите внимание на то, что этот класс наследует ORM класс описанный выше. Так же в члены-данные класса также записывается название таблицы, которую класс представляет и список полей этой таблицы.

На этом все! Благодарю за внимание! В следующем уроке, я уже рассмотрю динамическую форму на PHP и ее использование данной ORM библиотеки на данном примере, который может так же оказаться весьма полезным для Вас.





Евгений Болдырев