Здравствуйте! В этом уроке я покажу несложный пример реализации 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 библиотеки на данном примере, который может так же оказаться весьма полезным для Вас.