Советы/ресурсы/шаблоны для обучения внедрению базового ORM [закрыто]
Я видел различные фреймворки MVC, а также автономные фреймворки ORM для PHP, а также другие вопросы по ORM здесь; однако большинство вопросов задают для начала существующие фреймворки, а это не то, что я ищу. (Я также читал этот вопрос SO , но я не уверен, что с этим делать, поскольку ответы расплывчаты.)
Вместо этого я решил, что лучше всего научусь, запачкав руки и фактически написав свой собственный ORM, даже простой. Кроме меня на самом деле я не знаю, с чего начать, тем более что код, который я вижу в других ORM, настолько сложен.
С моим PHP 5.2.x (это важно)фреймворком MVC У меня есть базовый пользовательский уровень абстракции базы данных, который имеет:
- Очень простые методы, такие как
connect($host, $user, $pass, $base)
,query($sql, $binds)
, и т.д. - Подклассы для каждой поддерживаемой СУБД
- Класс (и соответствующие подклассы) для представления результирующих наборов SQL
Но не имейте:
- Функция активной записи, которая, как я предполагаю, является функцией ORM (поправьте меня, если я ошибаюсь)
РЕДАКТИРОВАТЬ: чтобы уточнить, у меня есть только уровень абстракции базы данных. У меня пока нет моделей, но когда я их реализую, я хочу, чтобы они были родными моделями ORM (так сказать), отсюда и этот вопрос.
Я немного прочитал об ORM, и, насколько я понимаю, они предоставляют средства для дальнейшего абстрагирования моделей данных из самой базы данных, представляя данные в виде не более чем классы/объекты на основе PHP; опять же, поправьте меня, если я ошибаюсь или что-то упустил.
Тем не менее, я хотел бы получить несколько простых советов от всех, кто более или менее знаком с фреймворками ORM. Есть ли что-нибудь еще, что мне нужно принять к сведению, простые академические образцы, на которые я могу сослаться, или ресурсы, которые я могу прочитать?
2 answers
Поскольку этот вопрос довольно старый, я думаю, вы уже пытались самостоятельно написать ORM. Тем не менее, поскольку я написал обычай ORM два года назад, я все равно хотел бы поделиться своим опытом и идеями.
Как уже было сказано, я внедрил пользовательский ORM два года назад и даже использовал его с некоторым успехом в проектах малого и среднего размера. Я интегрировал его в довольно популярную CMS, которой в то время (и даже сейчас) не хватало такой функциональности ORM. Кроме того, в то время популярные фреймворки, такие как Доктрина на самом деле не убедила меня. С тех пор многое изменилось, и Доктрина 2 эволюционировала в прочную основу, поэтому, если бы у меня сейчас был выбор между внедрением моего собственного ORM или использованием одной из популярных структур, таких как Доктрина 2, для производственного использования, это не было бы вообще вопросом - используйте существующие стабильные решения. НО: внедрение такой структуры (простым способом) было очень ценным учебным упражнением, и это очень помогло мне в работе с более крупными ORM с открытым исходным кодом, так как вы получаете лучшее понимание подводных камней и трудностей, связанных с объектно-реляционным отображением.
Реализовать базовую функциональность ORM не так уж сложно, но как только в игру вступает отображение отношений между объектами, это становится намного, намного сложнее/интереснее.
С чего я начал?
Что меня зацепило, так это книга Мартина Фаулерса Шаблоны архитектуры корпоративных приложений. Если вы хотите запрограммировать свой собственный ORM или даже если вы просто работаете с каким-то фреймворком ORM, купите эту книгу. Это один из наиболее ценных ресурсов, который охватывает многие базовые и передовые методы, касающиеся области объектно-реляционного отображения. Прочитав об этом, вы получите много замечательных идей о закономерностях, лежащих в основе ORM.
Базовая архитектура
Я решил, хотел бы я использовать скорее подход с активной записью или какой-то Сопоставитель данных. Это решение влияет на то, как данные из базы данных сопоставляются с сущностью. Я решил реализовать простой картограф данных, такой же подход, как Доктрина 2 или Гибернация в использовании Java. Активная запись - это подход к функциональности ORM (если это можно так назвать) в Zend Framework. Активная запись намного проще, чем сопоставитель данных, но также гораздо более ограничена. Ознакомьтесь с этими шаблонами и проверьте упомянутые фреймворки, вы довольно быстро поймете разницу. Если вы решите использовать данные Картограф, вам также следует ознакомиться с API отражения PHPS.
Запрос
У меня была амбициозная цель создать свой собственный язык запросов, очень похожий на DQL в Доктрине или HQL в спящем режиме. Вскоре я отказался от этого, так как написание пользовательского синтаксического анализатора/лексера SQL казалось слишком сложным (и это действительно так!). Что я сделал, так это реализовал объект запроса , чтобы инкапсулировать информацию о том, какая таблица участвует в запросе (это важно, так как вам необходимо сопоставить данные из базы данных с соответствующими классами для каждой таблицы).
Запрос объекта в моем ORM выглядел так:
public function findCountryByUid($countryUid) {
$queryObject = new QueryObject();
$queryObject->addSelectFields(new SelectFields('countries', '*'))
->addTable(new Table('countries'))
->addWhere('countries.uid = "' . intval($countryUid) . '"');
$res = $this->findByQuery($queryObject);
return $res->getSingleResult();
}
Конфигурация
Обычно вам также необходимо иметь какой-то формат конфигурации, Hibernate использует XML (среди прочего), Доктрина 2 использует аннотации PHP, EZКомпоненты используют массивы PHP в своем Постоянном объектном компоненте в качестве формата конфигурации. Это то, что я тоже использовал, это казалось естественным выбором, и CMS Я также работал с форматом конфигурации PHP.
С помощью этой конфигурации вы определяете
- какая таблица сопоставляется с каким классом
- какие поля должны быть сопоставлены экземпляру класса
- какой тип имеют поля таблицы (int, строка и т.д.)
- отношения между сущностями (например, класс пользователя имеет ссылку на класс группы пользователей)
- и т.д.
И это информация, которую вы используете в своем картографе данных для отображения результат БД для объектов.
Реализация
Я решил использовать сильный подход, основанный на тестировании, из-за сложной природы написания пользовательского ORM. TDD или нет, написание многих, многих модульных тестов - действительно хорошая идея для такого проекта. Кроме того: пачкайте руки и держите книгу Фаулерса поближе. ;-)
Как я уже сказал, это действительно стоило усилий, но я бы не хотел делать это снова, во многом из-за зрелых рамок, которые существуют в настоящее время.
Я больше не использую свой ORM, он работал, но ему не хватало многих функций, в том числе: отложенной загрузки, сопоставления компонентов, поддержки транзакций, кэширования, пользовательских типов, подготовленных операторов/параметров и т.д. И его производительность была недостаточно хороша для использования в крупномасштабных проектах.
Тем не менее, я надеюсь, что смогу дать вам некоторые отправные точки в области ORM, если вы их еще не знали. ;-)
Простой ORM может быть построен с использованием __get()
и __set()
и нескольких пользовательских методов (возможно, с использованием __call()
), вот простой псевдокод:
class ORM
{
private $table = null;
private $fields = array();
function __construct($table)
{
$this->table = $table;
}
function __get($key)
{
return isset($this->fields[$key]) ? $this->fields[$key] : false;
}
function __set($key, $value)
{
$this->fields[$key] = $value;
}
function load($id, $field = 'id')
{
// populate $this->fields with SELECT * FROM $this->table WHERE $field = $id;
}
function save()
{
if (isset($this->fields['id']))
{
// UPDATE $this->table SET $this->fields;
}
else
{
// INSERT INTO $this->table $this->fields;
}
}
}
$user = new ORM('user');
$user->name = 'name';
$user->pass = '1337';
$user->save();
Это всего лишь базовый пример, чтобы вы могли начать. Вы можете добавить дополнительную логику, используя магический метод __call()
, чтобы получать результаты по другим полям, например, кроме id
.
Имейте в виду, что приведенный мной пример не обрабатывает отношения, вот где различные реализации ORM действительно различаются, однако я обычно не доверяю никакому ORM обрабатывайте отношения для меня, так как они, как правило, намного медленнее и не создают эффективных запросов.