HyperActive Record – недо-ORM на CodeIgniter

в 11:40, , рубрики: codeigniter, innodb, mysql, orm, php, Веб-разработка, записи, объекты, связи, фреймворки, метки: , , , , , , , ,

HyperActive Record – недо ORM на CodeIgniter

Общее описание

HyperActive Record – это надстройка над классом DB для фреймворка CodeIgniter 2.0 и выше, позволяющая получать значения полей связанных с записью объектов по внешним ключам (foreign keys) без дополнительного описания связей и данных. Такая недо-ORM

Зачем это нужно?

HyperActive Record – недо ORM на CodeIgniter
Вот структура таблицы проектов, к примеру. Здесь видно, что есть связи с типом проекта, клиентом и менеджером
В обычном случае при получении данных при помощи ActiveRecord это выглядело бы так:
В модели:

                    $this->db->select();
        	    $this->db->from($this->table);
        	    $query = $this->db->get();
		    return $query->result();
                    

В результате:

array(1) {
  [0]=>
  object(stdClass)#19 (9) {
    ["id"]=>
    string(1) "2"
    ["name"]=>
    string(21) "Название проекта"
    ["date_start"]=>
    string(19) "2012-07-19 00:00:00"
    ["date_end"]=>
    string(19) "2012-07-31 00:00:00"
    ["description"]=>
    string(16) "Описание"
    ["project_types_id"]=>
    string(1) "1"
    ["clients_id"]=>
    string(1) "1"
    ["sum"]=>
    string(5) "12333"
    ["manager_id"]=>
    string(1) "1"
  }
}                    

Вместо того, чтобы получить имя клиента, тип проекта, информацию о менеджере мы получаем их id. Соответственно, чтобы получить значения, надо либо руками дописывать запросы, либо писать join в AR. И то, и другое не дает просветления и счастья, т.к. приходится делать постоянно и рутинно.
Да, конечно, можно взять готовую ORM, повозиться с прикручиванием ее к CodeIgniter (либо она у вас есть в поставке, если вы пользуетесь другим фреймворком), написать описание классов модели и связей… Стоп. Опять написать.
Т.к. я крайне ленив и не люблю постоянно делать одно и то же, на одном из проектов решил найти какую-то библиотеку, которая позволяла бы мне писать простой get и, при этом, тянула бы связанные с записью объекты без моего вмешательства. Не нашел, вот и получился HyperActive Record.
За идею и способ расширения стандартного драйвера DB спасибо Simon Emms

Возможности библиотеки:

  1. получение связанных с записью объектов со значениями всех их полей по Foreign keys.
  2. поддержка связей one-to-many, many-to-one, many-to-many
  3. получение связанных объектов только по указанным в запросе полям, без лишних данных
  4. неограниченное (пока) число уровней вложенности (если у проекта есть автор, у автора есть должность, то в результирующем объекте будут и проекты, и привязанные к ним авторы со значением их должностей)

Ограничения:

  1. пока только MySQL
  2. в MySQL только InnoDB, MyISAM не поддерживает внешние ключи
  3. в отличие от «взрослых» ORM, у полученных объектов невозможно вызвать методы моделей и т.д., это всего лишь данные

ToDo

  • Ограничение уровней вложенности рекурсии
  • Поддержка других драйверов баз CodeIgniter
  • Окультуривание кода

Документация

Установка

Скачайте и распакуйте библиотеку, положите файлы в папку core приложения (в архиве путь ведет как application/core, но у вас приложение может называться по-другому)

Все, больше не нужно никаких телодвижений для использования.

Использование

Делаем обычную конструкцию Active Record

                                $this->db->select();
        			$this->db->from($this->table);
        			$query = $this->db->get();
			        return $query->result(true,$this->table);
			        // или для получения одной записи
			        return $query->row(true,$this->table);
                    

Для обратной совместимости при отсутствии параметров у row() или result() вызывается родительская функция драйвера MySQL. $this->table – это базовая таблица, из которой нужно получить записи
Названия полей результирующего объекта, содержащих связанные записи, берутся из названий таблиц, содержащих связанные записи
Результат выполнения запроса (на примере той же таблицы, что приведена выше):

array(1) {
  [0]=>
  object(stdClass)#19 (14) {
    ["id"]=>
    string(1) "2"
    ["name"]=>
    string(21) "Название проекта"
    ["date_start"]=>
    string(19) "2012-07-19 00:00:00"
    ["date_end"]=>
    string(19) "2012-07-31 00:00:00"
    ["description"]=>
    string(16) "Описание"
    ["project_types_id"]=>
    string(1) "1"
    ["clients_id"]=>
    string(1) "1"
    ["sum"]=>
    string(5) "12333"
    ["manager_id"]=>
    string(1) "1"
    ["project_types"]=>
    object(stdClass)#23 (2) {
      ["id"]=>
      string(1) "1"
      ["name"]=>
      string(24) "Веб-сайт"
    }
    ["clients"]=>
    object(stdClass)#22 (2) {
      ["id"]=>
      string(1) "1"
      ["name"]=>
      string(12) "Иван Иванов"
    }
    ["users"]=>
    object(stdClass)#20 (7) {
      ["id"]=>
      string(1) "1"
      ["login"]=>
      string(11) "megalogin"
      ["password"]=>
      string(32) "202cb962ac59075b964b07152d234b70"
      ["name"]=>
      string(12) "John"
      ["surname"]=>
      string(18) "Doe"
      ["roles_id"]=>
      string(1) "2"
      ["roles"]=>
      object(stdClass)#28 (2) {
        ["id"]=>
        string(1) "2"
        ["name"]=>
        string(16) "Менеджер"
      }
    }
    ["project_files"]=>
    array(0) {
    }
    ["projects_milestones"]=>
    array(1) {
      [0]=>
      object(stdClass)#25 (7) {
        ["id"]=>
        string(1) "1"
        ["name"]=>
        string(10) "Начат"
        ["description"]=>
        string(0) ""
        ["count_files_needed"]=>
        string(1) "0"
        ["checklist_has_urls"]=>
        string(1) "0"
        ["final_file_needed"]=>
        string(1) "0"
        ["projects_id"]=>
        string(1) "2"
      }
    }
  }
}
                    

Для удобства работы и опять-таки уменьшения объема кода предлагается создать базовую модель с функциями get_list() и get() и в наследуемых моделях всего лишь устанавливать $this->table в конструкторе

Автор: NightWriter

* - обязательные к заполнению поля