Советы/ресурсы/шаблоны для обучения внедрению базового 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. Есть ли что-нибудь еще, что мне нужно принять к сведению, простые академические образцы, на которые я могу сослаться, или ресурсы, которые я могу прочитать?

Author: Community, 2010-05-22

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, если вы их еще не знали. ;-)

 11
Author: Max, 2012-11-13 14:01:59

Простой 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 обрабатывайте отношения для меня, так как они, как правило, намного медленнее и не создают эффективных запросов.

 2
Author: Alix Axel, 2010-05-22 18:45:33