Руководство по миграции на новую ORM

Одним из основных нововведений CakePHP 3.0 является полностью переписанное объектно-реляционное отображение (ORM). ORM используемая в версиях 1.x и 2.x и служившая нам длительное время имела некоторые проблемы, которые мы хотели исправить.

Например:

  • Frankenstein - это запись в таблице или таблица? И то и другое.
  • Несовместимый API - Model::read().
  • Не было объекта запроса - запросы всегда определялись как массивы, это имело некоторые ограничения и недостатки. Например это делало объединения и подзапросы намного сложнее.
  • Возвращаемые массивы - это было общим недовольством касающимся CakePHP, и, вероятно, в какой то степени повлияло на популярность фреймворка.
  • Не было объекта записи - это делало добавление методов форматирования сложным либо невозможным.
  • Содержимость - должна быть частью ORM, а не безумным классом поведения.
  • Рекурсивность - должна лучше контроллироваться определением ассоциаций, которые должны быть включены, а не уровнем вложенности рекурсии.
  • DboSource - это ужас, и Модель полагается на нее больше чем на источник данных. Это разделение должно быть проще и яснее.
  • Валидация - должна быть самостоятельной, сейчас это гигантская функция. Сделав ее переиспользуемой фреймворк станет более расширяемый.

В CakePHP 3.0 новая ORM решает эти и многие другие проблемы. Новая ORM фокусируется на реляционных данных. В будущем с помощью плагинов мы добавим в нее нереляционные хранилища, такие как ElasticSearch и т.д.

Устройство новой ORM

Новая ORM решает некоторые проблемы наличием более специализированных и сфокусированных классов. В прошлом вы использовали Model и Datasource для проведения всех операций. Теперь ORM разделена на несколько слоев:

  • Cake\Database\Connection - предоставляет независимую платформу для создания и использования соединений. Этот класс обеспечивает использование транзакций, выполнение запросов и предоставляет доступ к данным схемы.
  • Cake\Database\Dialect - классы этого пространства имен преобразуют запросы для работы с конкретной SQL платформой, учитывая их специфичиские ограничения.
  • Cake\Database\Type - это класс шлюза CakePHP системы преобразования типов данных в Базе Данных. Это подключаемый каркас, добавляющий абстрактные типы столбцов и обеспечивает соответствие между базой данных, PHP представлением и PDO bindings для каждого типа данных. Например столбцы типа datetime в вашем коде будут представлены в виде объектов DateTime.
  • Cake\ORM\Table - основная точка вхождения в новую ORM. Обеспечивает доступ к конкретной таблице. Управляет настройками отношений с другими таблицами, использует классы поведения, создает сущности и объекты запроса.
  • Cake\ORM\Behavior - базовый класс поведения, который работает похожим образом, как в предыдущих версиях CakePHP.
  • Cake\ORM\Query - изменчивый объект основанный на построителе запросов, заменяющий глубоко вложенные массивы, которые использовались в предыдущих версиях CakePHP.
  • Cake\ORM\ResultSet - коллекция результатов, которая предоставляет мощные инструменты для манипуляции совокупностью данных.
  • Cake\ORM\Entity - представляет собой одну запись в таблице. Предоставляет доступ к данным и сериализацию в различных форматах.

Вы познакомились с классами, с которыми вы будете взаимодействовать наиболее часто в новой ORM. Теперь взгляните на три наиболее самых важных класса: Table, Query и Entity - они решают большиноство задач в новой ORM и каждый имеет свое назначение.

Объект Table

Объекты класса Table предоставляют доступ к вашим данным. Они обрабатывают большинство задач, которые класс Model обрабатыватывал ранее. Класс Table обрабатывает такие задачи, как:

  • Создание запросов.
  • Предоставление finder’ов.
  • Валидация и сохрание сущностей.
  • Удаление сущностей.
  • Установка связей и доступ к связанным данным.
  • Страбатываение функций обратного вызова по событиям.
  • Взаимодействие с behaviors.

Глава Table Objects вы можете найти более подробную информацию по использованию объектов класса Table. При перемещении существующего кода класса Model, большинство кода оказалось а классе Table. Объекты класса Table не содержат SQL зависящего от конкретной платформы. Вместо этого они взаимодействуют с сущностями и построителем запросов. Объекты класса Table также взаимодействуют с behaviors и другими частями приложения через публичные события.

Объект Query

Хотя эти классы не являются классами которые вы будете строить самостроятельно, код вашего приложения будет широко использовать Query Builder, являющийся основным в новой ORM. Построитель запросов позволяет легко создавать простые и сложные запросы, включая те, которые ранее были очень сложными в ранних версиях CakePHP, например HAVING, UNION и подзапросы.

Различные вызовы метода find() в вашем приложении необходимо обновить для того, чтобы использовать новый построитель запросов. Объект Query несет ответственность за содержащиеся данные переданные в запрос, чтобы создать запрос без выполнения самого запроса. Он сотрудничает с connection/dialect для генерации специфического зависящего от платформы SQL кода, который выполняетсясоздавая на выходе ResultSet.

Объект Entity

В предыдущих версиях CakePHP класс Model возвращал массив данных, который не мог содержать какой либо логики или поведения. До тех пор, пока сообщество не сделало этот недостаток менее болезненным создав проект CakeEntity, массив результатов часто являлся причиной многих проблем разработчиков. В CakePHP 3.0 ORM всегда возвращает объект результирующего наборв, если вы явно не выключите эту функцию. Глава Entities охватывает различные задачи, которые вы можете выполнять с сущностями.

Сущности создаются одним из двух способов. Либо путем загрузки данных из Базы Данных, либо конвертацией данных запроса в сущности. Создав сущность вы можете манипулировать ее данными и сохранять сущность в таблицу взаимодействуя с объектом Table.

Ключевые отличия

В новой ORM большая часть кода была вынесена за пределы слоя Model. Есть много важных различий, которые важны в понимании того как новая ORM оперирует данными и как следует обновить ваш код.

Правила склонений обновлены

Вы могли заметить, что имена таблиц теперь следует именовать во множественном числе. В дополнение к именам таблиц во множественном числе, связи таблиц также именуются во множественном числе. Это отличается от Model где имена классов таблиц и связей именовались в единственном числе. Есть несколько причин для этих изменений:

  • Классы Table представляют собой коллекцию данных а не одиночные строки.
  • Связи соединяют таблицы вместе, описывая отношения между многими вещами.