SlideShare una empresa de Scribd logo
1 de 39
Толстая модель
       История разработки ORM

Шамин Михаил
Geometria.ru
Ведущий разработчик
Geometria.ru

• Главный фотохроникер страны
• 8 лет на рынке
• Представительство в 150 городах России, СНГ и
  Прибалтики
• Ежедневно 80 000 пользователей / 600 000 просмотров
• В понедельник 110 000 / 1 000 000
• Более 500 000 репортажей
• 15 000 000 фотографий
• 800 000 зарегистрированных пользователей
Почему понадобился свой ORM

Было

•   Наследство в виде залежей кода-лапши
•   Практически вся бизнес-логика в контроллерах
•   Вплоть до формирования select ов!
•   Некоторые экшены размером в 200 строк!
•   В роли модели - Zend_Db_Table
Почему понадобился свой ORM

Стало

• Стали использовать NoSQL решения, такие как Redis и
  Mongo
• Понадобилось решение, готовое работать с любым
  хранилищем, а не только SQL
• Есть ли что-то на рынке?
• Doctrine2 в alphа, еще сырая - страшно.
• Что делать?
• Пишем свой велосипед!
Выбор дизайна



                 Открываем книгу

              Мартина Фаулера
                   (Martin Fowler)

"Шаблоны корпоративных приложений"
  ("Patterns of Enterprise Application Architecture")
Выбор дизайна

         И находим то что нужно.

           Domain Model
                  или
     Модель предметной области
Поля модели. Как задавать ?

• В Zend_Db_Table_Row поля не прописаны явно, а
  берутся из схемы таблицы БД

• В Doctrine2 через задание private/protected свойств и
  генерацию getter/setter методов.
Поля модели. Решение:

Использовать DocBlock
Профиты:

•   Готовый шаблон для типов данных
•   Сразу в аннотации класса видны все поля модели
•   Автокомплит в IDE (Zend Studio, PhpStorm, NetBeans)
•   Быстрое создание классов
Zend_Reflection для генерации полей

/**
  * @property integer $id
  * @property string $title
  * @property string $body
  * @property boolean $hidden
  * @property integer $date
  **/
class Model_Post extends Geometria_Model
{
}
Zend_Reflection для генерации полей
После $post = new Model_Post();

свойство $_data будет выглядеть следующим образом:

class Model_Post extends Geometria_Model
{
    protected $_data = array(
        'id' => null,
        'title' => null,
        'body' => null,
        'hidden' => null,
        'date' => null,
    );
}
Доступ к полям

• Внешний доступ к полям обеспечивается через
  магические методы __get() и __set()

• Можно реализовать методы get<поле> и set<поле>,
  чтобы изменить логику установки/получения значения
  поля.
/**
  * ...
  * @property integer $date Unix timestamp
  */
class Model_Post extends Geometria_Model
...
public function setDate($value)
{
     if ($value instanceof Zend_Date) {
         $value = $value->getTimestamp();
     }
     $this->_data['date'] = $value;
}
Установка значения по умолчанию

class Model_Post extends Geometria_Model
...
public function getDate($value)
{
    if (null === $this->_data['date']) {
        $this->_data['date'] = time();
    }
    return $this->_data['date'];
}
Как хранить модель?

Используем DataMapper

• Маппер знает все о модели и о том, как и где еѐ
  хранить.
• Модель ничего не знает о хранилище.
• Логика домена отделена от persist логики
• Можно менять структуру бд или даже сменить
  хранилище, не меняя логику модели, всего лишь
  изменив маппер.
• Маппер выполняет CRUD операции
• Можно использовать любое хранилище: MySQL, Mongo,
  Redis, Config file, RESTApi и др.
Интерфейс маппера

interface Geometria_Model_Mapper_Interface
{
    public function create(Geometria_Model $model);

    public function update(Geometria_Model $model);

    public function delete(Geometria_Model $model);

    public function fetchOne($cond, $sort);

    public function fetchAll($cond, $sort, $limit, $skip);

    public function getCount($cond);
}
Работа с моделью

$post = new Model_Post();
$post->title = 'hello world!';
$post->body = 'foo bar';

$postMapper = new Model_Post_Mapper();
$postMapper->create($post);

echo $post->id; // 1 маппер сам проставил в модели
id
Выборки
• Условие $cond - простой массив
  имя поля => значение
• Сортировка $sort - тоже просто массив
  имя поля => (bool) направление сортировки
• Для более сложных выборок пишем отдельный метод

Выбрать 10 скрытых постов, начиная с самых новых

$mapper->fetchAll(
    array('hidden' => true),
    array('date' => false),
    10
);
Делаем ActiveRecord

Рассказываем модели, что у нее есть маппер.

• Делаем статический метод getMapper() который из
  специального контейнера
  Geometria_Model_Mapper_Manager достает нужный ей
  маппер
• Делаем у модели методы create(), update(), delete()


public function create()
{
    return self::getMapper()->create($this);
}
Теперь создание модели выглядит так:
$post = new Model_Post();
$post->title = 'hello world!';
$post->body = 'foo bar';
$post->create();

echo $post->id; // 1

А пост можно получить в одну строчку:

$post = Model_Post::getMapper()->fetchOne(
    array('id' => 1)
);
или так
$post = Model_Post::getMapper()->fetch(1);
Что вернет fetchAll()? Коллекцию!

• аналог Zend_Db_Table_Rowset
• Паттерн Record Set
• Позволяет выполнять массовые действия с набором
  моделей

interface Geometria_Model_Collection_Interface
extends Iterator, Countable
{
  public function append(Geometria_Model $model);
  public function prepend(Geometria_Model $model);
  public function populate(array $data);
  public function clear();
  public function toArray();
}
Нужен Paginator?
class Geometria_Paginator_Adapter_Mapper
  implements Zend_Paginator_Adapter_Interface
{
  public function __construct(
    Geometria_Model_Mapper_Interface $mapper,
    array $cond = null,
    array $sort = null
  )
  {
    $this->_mapper = $mapper;
    $this->_cond   = $cond;
    $this->_sort   = $sort;
  }
}
Нужен Paginator?
class Geometria_Paginator_Adapter_Mapper
  ...
  public function getItems($offset, $limit)
  {
    return $this->_mapper->fetchAll(
       $this->_cond,
       $this->_sort,
       $limit,
       $offset
    );
  }

 public function count()
 {
   return $this->_mapper->getCount(
      $this->_cond,
      $this->_sort
   );
 }
Хотим кешировать, логировать и тд.
• Используем декоратор для маппера
• Декортатор - это матрешка: в конструктор первого
  декоратора передаем маппер, в конструктор второго
  передаем первый декоратор и так далее
• Декоратор перехватывает "интересующие" его методы,
  и изменяет результат на ему угодный, остальные
  методы просто пропускает дальше.
• При инициализации маппера маппер-менеджер
  спрашивает у маппера, хочет ли он
  задекорироваться и оборачивает
  во все указанные декоратры
Примеры декораторов
Cache
• fetchOne(), fetchAll() - на основании переданного условия
  берет данные из кеша, или же просит маппер выполнить
  запрос и кеширует его результат.
• create(), update(), delete() - сбрасывает соответсвующий
  кеш.

Profiler
• Декоратор пропускает все запросы через себя,
   записывая в лог время выполнения запроса.

Identity Map
 • Кеширует результаты в памяти, чтобы маппер не
   выполнял одинаковые запросы дважды
Отношения

Раз уж строим ORM, то должны быть отношения между
сущностями.

• Отношения так же, как и поля, задаются в DocBlock
• Параметры описываются в спец формате
• При создании модели, создаются объекты-менеджеры
  отношений
• При обращении к полю, ссылающемуся на внешнюю
  сущность, объект-менеджер отношения делает запрос к
  внешнему мапперу и возвращает полученый объект.
Пример работы с отношениями
/**
  * ...
  * @property integer $authorId
  * @property Model_Author $author
[relation=belongsTo;localKey=authorId]
  */
class Model_Post extends Geometria_Model
{...}

$post = Model_Post::getMapper()->fetchOne(array('authorId'
=> 5));
$author = $post->author; // Model_Author

Менеджер отношения в данном случае выполнит запрос

Model_Author::getMapper()->fetchOne(array('id' => 5));
Виды отношений

• hasOne - one-to-one отношение
• belongsTo - тоже что и hasOne, но требует
  обязательного наличия объекта
• hasMany - one-to-many отношение
Полиморфические связи

Обеспечивают связь с несколькими видами сущностей, то
на какой тип сущности стоит ссылка определяет параметр
ownerType, в то время как параметр ownerTypeId
определяет id сущности.

/**
  * @property string $ownerType
  * @property integer $ownerId
  * @property Model_User|Model_Post $owner
[relation=polymorhic; localKey=ownerType;
localTypeKey=ownerId]
  */
class Model_Comment extends Geometria_Model
{..}
Тонкости отношений

$posts = Model_Post::getMapper()->fetchAll();

foreach ($posts as $post) {
    echo $post->title . ' by ' . $post->author;
}

Автор запрашивается при каждой итерации.

Если у нас 10 постов, значит мы сделаем 1 запрос на
получение постов и 10 запросов на получение авторов.
Итого 11 запросов - плохо!
Тонкости отношений

Решение:

$posts->fetchRelations('author');

Просим relation-manager получить всех авторов одним
запросом и проставить во всех постах коллекции.

Итого: 2 запроса, независимо от количества постов.
Тонкости отношений

А если у автора есть связь с картинкой-аватаркой?

$posts->fetchRelations('author', 'picture');

Что означает, что перед тем, как "распихать" всех авторов
по постам, у полученной коллекции авторов будет
вызван метод:

$authors->fetchRelations('picture');
Каскадные операции

У отношений можно прописать действие, которое будет
выполняться при удалении модели onDelete:
 • CASCADE - удалить все связанные зависимые модели
 • SET NULL - очистить значения внешних ключей

Это позволяет сохранять целостность связей внутри
нашей системы.
Жизнь без Join'ов

Как сделать выборку постов, написанных женщинами, если
посты используют одно хранилище, а авторы другое, и нет
возможности сделать join?

Использовать sphinx.

•   Создаем индекс в сфинксе для такого рода выборки.
•   Индексируем данные.
•   Создаем sphinx декоратор
•   Декоратор ищет id документов, удовлетворяющих
    поисковому запросу. И по этом списку id маппер
    возвращает коллекцию с результатом.
Что дало внедрение ORM

• Существенное ускорение разработки
• Время вхождения в чужой код значительно
  уменьшилось
• Использование Domain Driven Design позволяет
  говорить на языке предметной области, что повышает
  читаемость кода
• Логика приложения вынесена в отдельный слой
  сервисов. Что позволяет использовать ее не только в
  MVC, но и в CLI, например.
• Размер экшенов в контроллерах сократился до 10 строк.
Будет ли open source?

Будет, но позже )
Спасибо

Twitter: @munk13

МойКруг: http://munkie.moikrug.ru

Más contenido relacionado

La actualidad más candente

Лекция 11. Тестирование.
Лекция 11. Тестирование.Лекция 11. Тестирование.
Лекция 11. Тестирование.Roman Brovko
 
Профилирование и отладка Django
Профилирование и отладка DjangoПрофилирование и отладка Django
Профилирование и отладка DjangoVladimir Rudnyh
 
Лекция 13. Многопоточность и GIL
Лекция 13. Многопоточность и GILЛекция 13. Многопоточность и GIL
Лекция 13. Многопоточность и GILRoman Brovko
 
C#. От основ к эффективному коду
C#. От основ к эффективному кодуC#. От основ к эффективному коду
C#. От основ к эффективному кодуVasiliy Deynega
 
PG Day'14 Russia, PostgreSQL как платформа для разработки приложений, часть 2...
PG Day'14 Russia, PostgreSQL как платформа для разработки приложений, часть 2...PG Day'14 Russia, PostgreSQL как платформа для разработки приложений, часть 2...
PG Day'14 Russia, PostgreSQL как платформа для разработки приложений, часть 2...pgdayrussia
 
Объектное и прототипное программирование в Javascript
Объектное и прототипное программирование в JavascriptОбъектное и прототипное программирование в Javascript
Объектное и прототипное программирование в JavascriptDenis Latushkin
 
2014-08-02 01 Егор Непомнящих. jWidget - очередной MV*-фреймворк
2014-08-02 01 Егор Непомнящих. jWidget - очередной MV*-фреймворк2014-08-02 01 Егор Непомнящих. jWidget - очередной MV*-фреймворк
2014-08-02 01 Егор Непомнящих. jWidget - очередной MV*-фреймворкОмские ИТ-субботники
 
Лекция 4. Строки, байты, файлы и ввод/вывод.
 Лекция 4. Строки, байты, файлы и ввод/вывод. Лекция 4. Строки, байты, файлы и ввод/вывод.
Лекция 4. Строки, байты, файлы и ввод/вывод.Roman Brovko
 
Фундаментальные основы разработки под iOS. Павел Тайкало
Фундаментальные основы разработки под iOS. Павел ТайкалоФундаментальные основы разработки под iOS. Павел Тайкало
Фундаментальные основы разработки под iOS. Павел ТайкалоStanfy
 
Лекция 6. Классы 1.
Лекция 6. Классы 1.Лекция 6. Классы 1.
Лекция 6. Классы 1.Roman Brovko
 
YiiConf 2012 - Alexander Makarov - Yii2, что нового
YiiConf 2012 - Alexander Makarov - Yii2, что новогоYiiConf 2012 - Alexander Makarov - Yii2, что нового
YiiConf 2012 - Alexander Makarov - Yii2, что новогоAlexander Makarov
 
Хранение данных в iPhone. (FMDB, SQL-Persistence, CoreData)
Хранение данных в iPhone. (FMDB, SQL-Persistence, CoreData)Хранение данных в iPhone. (FMDB, SQL-Persistence, CoreData)
Хранение данных в iPhone. (FMDB, SQL-Persistence, CoreData)Yandex
 
Yii 2. Что нового?
Yii 2. Что нового?Yii 2. Что нового?
Yii 2. Что нового?yiiconf
 
Лекция 3. Декораторы и модуль functools.
Лекция 3. Декораторы и модуль functools.Лекция 3. Декораторы и модуль functools.
Лекция 3. Декораторы и модуль functools.Roman Brovko
 
Лекция 9. Модули, пакеты и система импорта.
Лекция 9. Модули, пакеты и система импорта.Лекция 9. Модули, пакеты и система импорта.
Лекция 9. Модули, пакеты и система импорта.Roman Brovko
 
Лекция 1. Начало.
Лекция 1. Начало.Лекция 1. Начало.
Лекция 1. Начало.Roman Brovko
 
Магия метаклассов
Магия метаклассовМагия метаклассов
Магия метаклассовAndrey Zakharevich
 
Влад Ковташ — Yap Database
Влад Ковташ — Yap DatabaseВлад Ковташ — Yap Database
Влад Ковташ — Yap DatabaseCocoaHeads
 
SQL Tricky (Иван Фролков)
SQL Tricky (Иван Фролков)SQL Tricky (Иван Фролков)
SQL Tricky (Иван Фролков)Ontico
 

La actualidad más candente (20)

Лекция 11. Тестирование.
Лекция 11. Тестирование.Лекция 11. Тестирование.
Лекция 11. Тестирование.
 
Javascript 1
Javascript 1Javascript 1
Javascript 1
 
Профилирование и отладка Django
Профилирование и отладка DjangoПрофилирование и отладка Django
Профилирование и отладка Django
 
Лекция 13. Многопоточность и GIL
Лекция 13. Многопоточность и GILЛекция 13. Многопоточность и GIL
Лекция 13. Многопоточность и GIL
 
C#. От основ к эффективному коду
C#. От основ к эффективному кодуC#. От основ к эффективному коду
C#. От основ к эффективному коду
 
PG Day'14 Russia, PostgreSQL как платформа для разработки приложений, часть 2...
PG Day'14 Russia, PostgreSQL как платформа для разработки приложений, часть 2...PG Day'14 Russia, PostgreSQL как платформа для разработки приложений, часть 2...
PG Day'14 Russia, PostgreSQL как платформа для разработки приложений, часть 2...
 
Объектное и прототипное программирование в Javascript
Объектное и прототипное программирование в JavascriptОбъектное и прототипное программирование в Javascript
Объектное и прототипное программирование в Javascript
 
2014-08-02 01 Егор Непомнящих. jWidget - очередной MV*-фреймворк
2014-08-02 01 Егор Непомнящих. jWidget - очередной MV*-фреймворк2014-08-02 01 Егор Непомнящих. jWidget - очередной MV*-фреймворк
2014-08-02 01 Егор Непомнящих. jWidget - очередной MV*-фреймворк
 
Лекция 4. Строки, байты, файлы и ввод/вывод.
 Лекция 4. Строки, байты, файлы и ввод/вывод. Лекция 4. Строки, байты, файлы и ввод/вывод.
Лекция 4. Строки, байты, файлы и ввод/вывод.
 
Фундаментальные основы разработки под iOS. Павел Тайкало
Фундаментальные основы разработки под iOS. Павел ТайкалоФундаментальные основы разработки под iOS. Павел Тайкало
Фундаментальные основы разработки под iOS. Павел Тайкало
 
Лекция 6. Классы 1.
Лекция 6. Классы 1.Лекция 6. Классы 1.
Лекция 6. Классы 1.
 
YiiConf 2012 - Alexander Makarov - Yii2, что нового
YiiConf 2012 - Alexander Makarov - Yii2, что новогоYiiConf 2012 - Alexander Makarov - Yii2, что нового
YiiConf 2012 - Alexander Makarov - Yii2, что нового
 
Хранение данных в iPhone. (FMDB, SQL-Persistence, CoreData)
Хранение данных в iPhone. (FMDB, SQL-Persistence, CoreData)Хранение данных в iPhone. (FMDB, SQL-Persistence, CoreData)
Хранение данных в iPhone. (FMDB, SQL-Persistence, CoreData)
 
Yii 2. Что нового?
Yii 2. Что нового?Yii 2. Что нового?
Yii 2. Что нового?
 
Лекция 3. Декораторы и модуль functools.
Лекция 3. Декораторы и модуль functools.Лекция 3. Декораторы и модуль functools.
Лекция 3. Декораторы и модуль functools.
 
Лекция 9. Модули, пакеты и система импорта.
Лекция 9. Модули, пакеты и система импорта.Лекция 9. Модули, пакеты и система импорта.
Лекция 9. Модули, пакеты и система импорта.
 
Лекция 1. Начало.
Лекция 1. Начало.Лекция 1. Начало.
Лекция 1. Начало.
 
Магия метаклассов
Магия метаклассовМагия метаклассов
Магия метаклассов
 
Влад Ковташ — Yap Database
Влад Ковташ — Yap DatabaseВлад Ковташ — Yap Database
Влад Ковташ — Yap Database
 
SQL Tricky (Иван Фролков)
SQL Tricky (Иван Фролков)SQL Tricky (Иван Фролков)
SQL Tricky (Иван Фролков)
 

Destacado

Профессиональная разработка в суровом Enterprise
Профессиональная разработка в суровом EnterpriseПрофессиональная разработка в суровом Enterprise
Профессиональная разработка в суровом EnterpriseAlexander Granin
 
Orm на no sql через jpa. Павел Вейник
Orm на no sql через jpa. Павел ВейникOrm на no sql через jpa. Павел Вейник
Orm на no sql через jpa. Павел ВейникAlina Dolgikh
 
Hibernate working with criteria- Basic Introduction
Hibernate working with criteria- Basic IntroductionHibernate working with criteria- Basic Introduction
Hibernate working with criteria- Basic IntroductionEr. Gaurav Kumar
 
Hibernate Tutorial
Hibernate TutorialHibernate Tutorial
Hibernate TutorialRam132
 
Spring Framework - Validation
Spring Framework - ValidationSpring Framework - Validation
Spring Framework - ValidationDzmitry Naskou
 
Spring Framework - Data Access
Spring Framework - Data AccessSpring Framework - Data Access
Spring Framework - Data AccessDzmitry Naskou
 
Spring Framework - Expression Language
Spring Framework - Expression LanguageSpring Framework - Expression Language
Spring Framework - Expression LanguageDzmitry Naskou
 
Spring Framework - Web Flow
Spring Framework - Web FlowSpring Framework - Web Flow
Spring Framework - Web FlowDzmitry Naskou
 
Hibernate ORM: Tips, Tricks, and Performance Techniques
Hibernate ORM: Tips, Tricks, and Performance TechniquesHibernate ORM: Tips, Tricks, and Performance Techniques
Hibernate ORM: Tips, Tricks, and Performance TechniquesBrett Meyer
 
Java Hibernate Programming with Architecture Diagram and Example
Java Hibernate Programming with Architecture Diagram and ExampleJava Hibernate Programming with Architecture Diagram and Example
Java Hibernate Programming with Architecture Diagram and Examplekamal kotecha
 
Introduction to hibernate
Introduction to hibernateIntroduction to hibernate
Introduction to hibernatehr1383
 
ORM, JPA, & Hibernate Overview
ORM, JPA, & Hibernate OverviewORM, JPA, & Hibernate Overview
ORM, JPA, & Hibernate OverviewBrett Meyer
 
Spring Framework - MVC
Spring Framework - MVCSpring Framework - MVC
Spring Framework - MVCDzmitry Naskou
 
Hibernate Presentation
Hibernate  PresentationHibernate  Presentation
Hibernate Presentationguest11106b
 
Spring Framework - Spring Security
Spring Framework - Spring SecuritySpring Framework - Spring Security
Spring Framework - Spring SecurityDzmitry Naskou
 
Java Persistence API (JPA) Step By Step
Java Persistence API (JPA) Step By StepJava Persistence API (JPA) Step By Step
Java Persistence API (JPA) Step By StepGuo Albert
 
Introduction to Spring Framework
Introduction to Spring FrameworkIntroduction to Spring Framework
Introduction to Spring Framework Serhat Can
 

Destacado (20)

Профессиональная разработка в суровом Enterprise
Профессиональная разработка в суровом EnterpriseПрофессиональная разработка в суровом Enterprise
Профессиональная разработка в суровом Enterprise
 
Orm на no sql через jpa. Павел Вейник
Orm на no sql через jpa. Павел ВейникOrm на no sql через jpa. Павел Вейник
Orm на no sql через jpa. Павел Вейник
 
Hibernate working with criteria- Basic Introduction
Hibernate working with criteria- Basic IntroductionHibernate working with criteria- Basic Introduction
Hibernate working with criteria- Basic Introduction
 
Hibernate Tutorial
Hibernate TutorialHibernate Tutorial
Hibernate Tutorial
 
Spring Framework - Validation
Spring Framework - ValidationSpring Framework - Validation
Spring Framework - Validation
 
Hibernate
HibernateHibernate
Hibernate
 
Spring Framework - Data Access
Spring Framework - Data AccessSpring Framework - Data Access
Spring Framework - Data Access
 
Spring Framework - Expression Language
Spring Framework - Expression LanguageSpring Framework - Expression Language
Spring Framework - Expression Language
 
Hibernate in Action
Hibernate in ActionHibernate in Action
Hibernate in Action
 
Spring Framework - Web Flow
Spring Framework - Web FlowSpring Framework - Web Flow
Spring Framework - Web Flow
 
Hibernate ORM: Tips, Tricks, and Performance Techniques
Hibernate ORM: Tips, Tricks, and Performance TechniquesHibernate ORM: Tips, Tricks, and Performance Techniques
Hibernate ORM: Tips, Tricks, and Performance Techniques
 
Java Hibernate Programming with Architecture Diagram and Example
Java Hibernate Programming with Architecture Diagram and ExampleJava Hibernate Programming with Architecture Diagram and Example
Java Hibernate Programming with Architecture Diagram and Example
 
JPA and Hibernate
JPA and HibernateJPA and Hibernate
JPA and Hibernate
 
Introduction to hibernate
Introduction to hibernateIntroduction to hibernate
Introduction to hibernate
 
ORM, JPA, & Hibernate Overview
ORM, JPA, & Hibernate OverviewORM, JPA, & Hibernate Overview
ORM, JPA, & Hibernate Overview
 
Spring Framework - MVC
Spring Framework - MVCSpring Framework - MVC
Spring Framework - MVC
 
Hibernate Presentation
Hibernate  PresentationHibernate  Presentation
Hibernate Presentation
 
Spring Framework - Spring Security
Spring Framework - Spring SecuritySpring Framework - Spring Security
Spring Framework - Spring Security
 
Java Persistence API (JPA) Step By Step
Java Persistence API (JPA) Step By StepJava Persistence API (JPA) Step By Step
Java Persistence API (JPA) Step By Step
 
Introduction to Spring Framework
Introduction to Spring FrameworkIntroduction to Spring Framework
Introduction to Spring Framework
 

Similar a ZFConf 2011: Толстая модель: История разработки собственного ORM (Михаил Шамин)

Ice Php Framework Preview Release
Ice Php Framework Preview ReleaseIce Php Framework Preview Release
Ice Php Framework Preview ReleaseDenis Shestakov
 
Импорт данных с фреймворком Migrate. Владислав Богатырев.
Импорт данных с фреймворком Migrate. Владислав Богатырев.Импорт данных с фреймворком Migrate. Владислав Богатырев.
Импорт данных с фреймворком Migrate. Владислав Богатырев.DrupalCampDN
 
Выжить с помощью ООП. Максим Гопей
Выжить с помощью ООП. Максим ГопейВыжить с помощью ООП. Максим Гопей
Выжить с помощью ООП. Максим ГопейEatDog
 
Михаил Давыдов "Масштабируемые JavaScript-приложения"
Михаил Давыдов "Масштабируемые JavaScript-приложения"Михаил Давыдов "Масштабируемые JavaScript-приложения"
Михаил Давыдов "Масштабируемые JavaScript-приложения"Yandex
 
Расширенное кеширование Doctrine2 (Ильяс Салихов, Intaro)
Расширенное кеширование Doctrine2 (Ильяс Салихов, Intaro)Расширенное кеширование Doctrine2 (Ильяс Салихов, Intaro)
Расширенное кеширование Doctrine2 (Ильяс Салихов, Intaro)Symfoniacs
 
Расширенное кеширование в Doctrine2
Расширенное кеширование в Doctrine2Расширенное кеширование в Doctrine2
Расширенное кеширование в Doctrine2Ilyas Salikhov
 
Архитектура кода нового 2ГИС Web API или куда мы дели MVC
Архитектура кода нового 2ГИС Web API или куда мы дели MVCАрхитектура кода нового 2ГИС Web API или куда мы дели MVC
Архитектура кода нового 2ГИС Web API или куда мы дели MVCDevDay
 
Корпоративное приложение на Rails
Корпоративное приложение на RailsКорпоративное приложение на Rails
Корпоративное приложение на RailsAndrei Kaleshka
 
Метапрограммирование с примерами на JavaScript
Метапрограммирование с примерами на JavaScriptМетапрограммирование с примерами на JavaScript
Метапрограммирование с примерами на JavaScriptTimur Shemsedinov
 
Ember.js ответ на почти все вопросы - java script frameworks day 2014
Ember.js   ответ на почти все вопросы - java script frameworks day 2014Ember.js   ответ на почти все вопросы - java script frameworks day 2014
Ember.js ответ на почти все вопросы - java script frameworks day 2014Andrey Listochkin
 
Ruby on Rails. Работа с моделями — продолжение
Ruby on Rails. Работа с моделями — продолжениеRuby on Rails. Работа с моделями — продолжение
Ruby on Rails. Работа с моделями — продолжениеDigital-агентство Мэйк
 
ZFConf 2010: Zend Framework and Doctrine
ZFConf 2010: Zend Framework and DoctrineZFConf 2010: Zend Framework and Doctrine
ZFConf 2010: Zend Framework and DoctrineZFConf Conference
 
Михаил Давыдов "Масштабируемые JavaScript-приложения"
Михаил Давыдов "Масштабируемые JavaScript-приложения"Михаил Давыдов "Масштабируемые JavaScript-приложения"
Михаил Давыдов "Масштабируемые JavaScript-приложения"Yandex
 
"Деплой кода процедур" Мурат Кабилов (Avito)
"Деплой кода процедур" Мурат Кабилов (Avito)"Деплой кода процедур" Мурат Кабилов (Avito)
"Деплой кода процедур" Мурат Кабилов (Avito)AvitoTech
 

Similar a ZFConf 2011: Толстая модель: История разработки собственного ORM (Михаил Шамин) (20)

Ice Php Framework Preview Release
Ice Php Framework Preview ReleaseIce Php Framework Preview Release
Ice Php Framework Preview Release
 
Survive with OOP
Survive with OOPSurvive with OOP
Survive with OOP
 
Импорт данных с фреймворком Migrate. Владислав Богатырев.
Импорт данных с фреймворком Migrate. Владислав Богатырев.Импорт данных с фреймворком Migrate. Владислав Богатырев.
Импорт данных с фреймворком Migrate. Владислав Богатырев.
 
Выжить с помощью ООП. Максим Гопей
Выжить с помощью ООП. Максим ГопейВыжить с помощью ООП. Максим Гопей
Выжить с помощью ООП. Максим Гопей
 
Zend Framework и Doctrine
Zend Framework и DoctrineZend Framework и Doctrine
Zend Framework и Doctrine
 
Михаил Давыдов "Масштабируемые JavaScript-приложения"
Михаил Давыдов "Масштабируемые JavaScript-приложения"Михаил Давыдов "Масштабируемые JavaScript-приложения"
Михаил Давыдов "Масштабируемые JavaScript-приложения"
 
бегун
бегунбегун
бегун
 
Расширенное кеширование Doctrine2 (Ильяс Салихов, Intaro)
Расширенное кеширование Doctrine2 (Ильяс Салихов, Intaro)Расширенное кеширование Doctrine2 (Ильяс Салихов, Intaro)
Расширенное кеширование Doctrine2 (Ильяс Салихов, Intaro)
 
Расширенное кеширование в Doctrine2
Расширенное кеширование в Doctrine2Расширенное кеширование в Doctrine2
Расширенное кеширование в Doctrine2
 
Архитектура кода нового 2ГИС Web API или куда мы дели MVC
Архитектура кода нового 2ГИС Web API или куда мы дели MVCАрхитектура кода нового 2ГИС Web API или куда мы дели MVC
Архитектура кода нового 2ГИС Web API или куда мы дели MVC
 
Корпоративное приложение на Rails
Корпоративное приложение на RailsКорпоративное приложение на Rails
Корпоративное приложение на Rails
 
UWDC 2013, Yii2
UWDC 2013, Yii2UWDC 2013, Yii2
UWDC 2013, Yii2
 
Метапрограммирование с примерами на JavaScript
Метапрограммирование с примерами на JavaScriptМетапрограммирование с примерами на JavaScript
Метапрограммирование с примерами на JavaScript
 
Yserver
YserverYserver
Yserver
 
Ember.js ответ на почти все вопросы - java script frameworks day 2014
Ember.js   ответ на почти все вопросы - java script frameworks day 2014Ember.js   ответ на почти все вопросы - java script frameworks day 2014
Ember.js ответ на почти все вопросы - java script frameworks day 2014
 
бегун
бегунбегун
бегун
 
Ruby on Rails. Работа с моделями — продолжение
Ruby on Rails. Работа с моделями — продолжениеRuby on Rails. Работа с моделями — продолжение
Ruby on Rails. Работа с моделями — продолжение
 
ZFConf 2010: Zend Framework and Doctrine
ZFConf 2010: Zend Framework and DoctrineZFConf 2010: Zend Framework and Doctrine
ZFConf 2010: Zend Framework and Doctrine
 
Михаил Давыдов "Масштабируемые JavaScript-приложения"
Михаил Давыдов "Масштабируемые JavaScript-приложения"Михаил Давыдов "Масштабируемые JavaScript-приложения"
Михаил Давыдов "Масштабируемые JavaScript-приложения"
 
"Деплой кода процедур" Мурат Кабилов (Avito)
"Деплой кода процедур" Мурат Кабилов (Avito)"Деплой кода процедур" Мурат Кабилов (Avito)
"Деплой кода процедур" Мурат Кабилов (Avito)
 

Más de ZFConf Conference

ZFConf 2012: Кеш без промахов средствами Zend Framework 2 (Евгений Шпилевский)
ZFConf 2012: Кеш без промахов средствами Zend Framework 2 (Евгений Шпилевский)ZFConf 2012: Кеш без промахов средствами Zend Framework 2 (Евгений Шпилевский)
ZFConf 2012: Кеш без промахов средствами Zend Framework 2 (Евгений Шпилевский)ZFConf Conference
 
ZFConf 2012: Dependency Management в PHP и Zend Framework 2 (Кирилл Чебунин)
ZFConf 2012: Dependency Management в PHP и Zend Framework 2 (Кирилл Чебунин)ZFConf 2012: Dependency Management в PHP и Zend Framework 2 (Кирилл Чебунин)
ZFConf 2012: Dependency Management в PHP и Zend Framework 2 (Кирилл Чебунин)ZFConf Conference
 
ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)
ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)
ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)ZFConf Conference
 
ZFConf 2012: Проектирование архитектуры, внедрение и организация процесса раз...
ZFConf 2012: Проектирование архитектуры, внедрение и организация процесса раз...ZFConf 2012: Проектирование архитектуры, внедрение и организация процесса раз...
ZFConf 2012: Проектирование архитектуры, внедрение и организация процесса раз...ZFConf Conference
 
ZFConf 2012: Реализация доступа к СУБД IBM DB2 посредством встраиваемого SQL ...
ZFConf 2012: Реализация доступа к СУБД IBM DB2 посредством встраиваемого SQL ...ZFConf 2012: Реализация доступа к СУБД IBM DB2 посредством встраиваемого SQL ...
ZFConf 2012: Реализация доступа к СУБД IBM DB2 посредством встраиваемого SQL ...ZFConf Conference
 
ZFConf 2012: Code Generation и Scaffolding в Zend Framework 2 (Виктор Фараздаги)
ZFConf 2012: Code Generation и Scaffolding в Zend Framework 2 (Виктор Фараздаги)ZFConf 2012: Code Generation и Scaffolding в Zend Framework 2 (Виктор Фараздаги)
ZFConf 2012: Code Generation и Scaffolding в Zend Framework 2 (Виктор Фараздаги)ZFConf Conference
 
ZFConf 2012: Zend Framework 2, a quick start (Enrico Zimuel)
ZFConf 2012: Zend Framework 2, a quick start (Enrico Zimuel)ZFConf 2012: Zend Framework 2, a quick start (Enrico Zimuel)
ZFConf 2012: Zend Framework 2, a quick start (Enrico Zimuel)ZFConf Conference
 
ZFConf 2011: Создание REST-API для сторонних разработчиков и мобильных устрой...
ZFConf 2011: Создание REST-API для сторонних разработчиков и мобильных устрой...ZFConf 2011: Создание REST-API для сторонних разработчиков и мобильных устрой...
ZFConf 2011: Создание REST-API для сторонних разработчиков и мобильных устрой...ZFConf Conference
 
ZFConf 2011: Что такое Sphinx, зачем он вообще нужен и как его использовать с...
ZFConf 2011: Что такое Sphinx, зачем он вообще нужен и как его использовать с...ZFConf 2011: Что такое Sphinx, зачем он вообще нужен и как его использовать с...
ZFConf 2011: Что такое Sphinx, зачем он вообще нужен и как его использовать с...ZFConf Conference
 
ZFConf 2011: Как может помочь среда разработки при написании приложения на Ze...
ZFConf 2011: Как может помочь среда разработки при написании приложения на Ze...ZFConf 2011: Как может помочь среда разработки при написании приложения на Ze...
ZFConf 2011: Как может помочь среда разработки при написании приложения на Ze...ZFConf Conference
 
ZFConf 2011: Разделение труда: Организация многозадачной, распределенной сист...
ZFConf 2011: Разделение труда: Организация многозадачной, распределенной сист...ZFConf 2011: Разделение труда: Организация многозадачной, распределенной сист...
ZFConf 2011: Разделение труда: Организация многозадачной, распределенной сист...ZFConf Conference
 
ZFConf 2011: Гибкая архитектура Zend Framework приложений с использованием De...
ZFConf 2011: Гибкая архитектура Zend Framework приложений с использованием De...ZFConf 2011: Гибкая архитектура Zend Framework приложений с использованием De...
ZFConf 2011: Гибкая архитектура Zend Framework приложений с использованием De...ZFConf Conference
 
ZFConf 2011: Behavior Driven Development в PHP и Zend Framework (Константин К...
ZFConf 2011: Behavior Driven Development в PHP и Zend Framework (Константин К...ZFConf 2011: Behavior Driven Development в PHP и Zend Framework (Константин К...
ZFConf 2011: Behavior Driven Development в PHP и Zend Framework (Константин К...ZFConf Conference
 
ZFConf 2011: Воюем за ресурсы: Повышение производительности Zend Framework пр...
ZFConf 2011: Воюем за ресурсы: Повышение производительности Zend Framework пр...ZFConf 2011: Воюем за ресурсы: Повышение производительности Zend Framework пр...
ZFConf 2011: Воюем за ресурсы: Повышение производительности Zend Framework пр...ZFConf Conference
 
ZFConf 2010: History of e-Shtab.ru
ZFConf 2010: History of e-Shtab.ruZFConf 2010: History of e-Shtab.ru
ZFConf 2010: History of e-Shtab.ruZFConf Conference
 
ZFConf 2010: Fotostrana.ru: Prototyping Project with Zend Framework
ZFConf 2010: Fotostrana.ru: Prototyping Project with Zend FrameworkZFConf 2010: Fotostrana.ru: Prototyping Project with Zend Framework
ZFConf 2010: Fotostrana.ru: Prototyping Project with Zend FrameworkZFConf Conference
 
ZFConf 2010: Performance of Zend Framework Applications
ZFConf 2010: Performance of Zend Framework ApplicationsZFConf 2010: Performance of Zend Framework Applications
ZFConf 2010: Performance of Zend Framework ApplicationsZFConf Conference
 
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...ZFConf Conference
 
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 1)
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 1)ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 1)
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 1)ZFConf Conference
 
ZFConf 2010: What News Zend Framework 2.0 Brings to Us
ZFConf 2010: What News Zend Framework 2.0 Brings to UsZFConf 2010: What News Zend Framework 2.0 Brings to Us
ZFConf 2010: What News Zend Framework 2.0 Brings to UsZFConf Conference
 

Más de ZFConf Conference (20)

ZFConf 2012: Кеш без промахов средствами Zend Framework 2 (Евгений Шпилевский)
ZFConf 2012: Кеш без промахов средствами Zend Framework 2 (Евгений Шпилевский)ZFConf 2012: Кеш без промахов средствами Zend Framework 2 (Евгений Шпилевский)
ZFConf 2012: Кеш без промахов средствами Zend Framework 2 (Евгений Шпилевский)
 
ZFConf 2012: Dependency Management в PHP и Zend Framework 2 (Кирилл Чебунин)
ZFConf 2012: Dependency Management в PHP и Zend Framework 2 (Кирилл Чебунин)ZFConf 2012: Dependency Management в PHP и Zend Framework 2 (Кирилл Чебунин)
ZFConf 2012: Dependency Management в PHP и Zend Framework 2 (Кирилл Чебунин)
 
ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)
ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)
ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)
 
ZFConf 2012: Проектирование архитектуры, внедрение и организация процесса раз...
ZFConf 2012: Проектирование архитектуры, внедрение и организация процесса раз...ZFConf 2012: Проектирование архитектуры, внедрение и организация процесса раз...
ZFConf 2012: Проектирование архитектуры, внедрение и организация процесса раз...
 
ZFConf 2012: Реализация доступа к СУБД IBM DB2 посредством встраиваемого SQL ...
ZFConf 2012: Реализация доступа к СУБД IBM DB2 посредством встраиваемого SQL ...ZFConf 2012: Реализация доступа к СУБД IBM DB2 посредством встраиваемого SQL ...
ZFConf 2012: Реализация доступа к СУБД IBM DB2 посредством встраиваемого SQL ...
 
ZFConf 2012: Code Generation и Scaffolding в Zend Framework 2 (Виктор Фараздаги)
ZFConf 2012: Code Generation и Scaffolding в Zend Framework 2 (Виктор Фараздаги)ZFConf 2012: Code Generation и Scaffolding в Zend Framework 2 (Виктор Фараздаги)
ZFConf 2012: Code Generation и Scaffolding в Zend Framework 2 (Виктор Фараздаги)
 
ZFConf 2012: Zend Framework 2, a quick start (Enrico Zimuel)
ZFConf 2012: Zend Framework 2, a quick start (Enrico Zimuel)ZFConf 2012: Zend Framework 2, a quick start (Enrico Zimuel)
ZFConf 2012: Zend Framework 2, a quick start (Enrico Zimuel)
 
ZFConf 2011: Создание REST-API для сторонних разработчиков и мобильных устрой...
ZFConf 2011: Создание REST-API для сторонних разработчиков и мобильных устрой...ZFConf 2011: Создание REST-API для сторонних разработчиков и мобильных устрой...
ZFConf 2011: Создание REST-API для сторонних разработчиков и мобильных устрой...
 
ZFConf 2011: Что такое Sphinx, зачем он вообще нужен и как его использовать с...
ZFConf 2011: Что такое Sphinx, зачем он вообще нужен и как его использовать с...ZFConf 2011: Что такое Sphinx, зачем он вообще нужен и как его использовать с...
ZFConf 2011: Что такое Sphinx, зачем он вообще нужен и как его использовать с...
 
ZFConf 2011: Как может помочь среда разработки при написании приложения на Ze...
ZFConf 2011: Как может помочь среда разработки при написании приложения на Ze...ZFConf 2011: Как может помочь среда разработки при написании приложения на Ze...
ZFConf 2011: Как может помочь среда разработки при написании приложения на Ze...
 
ZFConf 2011: Разделение труда: Организация многозадачной, распределенной сист...
ZFConf 2011: Разделение труда: Организация многозадачной, распределенной сист...ZFConf 2011: Разделение труда: Организация многозадачной, распределенной сист...
ZFConf 2011: Разделение труда: Организация многозадачной, распределенной сист...
 
ZFConf 2011: Гибкая архитектура Zend Framework приложений с использованием De...
ZFConf 2011: Гибкая архитектура Zend Framework приложений с использованием De...ZFConf 2011: Гибкая архитектура Zend Framework приложений с использованием De...
ZFConf 2011: Гибкая архитектура Zend Framework приложений с использованием De...
 
ZFConf 2011: Behavior Driven Development в PHP и Zend Framework (Константин К...
ZFConf 2011: Behavior Driven Development в PHP и Zend Framework (Константин К...ZFConf 2011: Behavior Driven Development в PHP и Zend Framework (Константин К...
ZFConf 2011: Behavior Driven Development в PHP и Zend Framework (Константин К...
 
ZFConf 2011: Воюем за ресурсы: Повышение производительности Zend Framework пр...
ZFConf 2011: Воюем за ресурсы: Повышение производительности Zend Framework пр...ZFConf 2011: Воюем за ресурсы: Повышение производительности Zend Framework пр...
ZFConf 2011: Воюем за ресурсы: Повышение производительности Zend Framework пр...
 
ZFConf 2010: History of e-Shtab.ru
ZFConf 2010: History of e-Shtab.ruZFConf 2010: History of e-Shtab.ru
ZFConf 2010: History of e-Shtab.ru
 
ZFConf 2010: Fotostrana.ru: Prototyping Project with Zend Framework
ZFConf 2010: Fotostrana.ru: Prototyping Project with Zend FrameworkZFConf 2010: Fotostrana.ru: Prototyping Project with Zend Framework
ZFConf 2010: Fotostrana.ru: Prototyping Project with Zend Framework
 
ZFConf 2010: Performance of Zend Framework Applications
ZFConf 2010: Performance of Zend Framework ApplicationsZFConf 2010: Performance of Zend Framework Applications
ZFConf 2010: Performance of Zend Framework Applications
 
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
 
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 1)
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 1)ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 1)
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 1)
 
ZFConf 2010: What News Zend Framework 2.0 Brings to Us
ZFConf 2010: What News Zend Framework 2.0 Brings to UsZFConf 2010: What News Zend Framework 2.0 Brings to Us
ZFConf 2010: What News Zend Framework 2.0 Brings to Us
 

ZFConf 2011: Толстая модель: История разработки собственного ORM (Михаил Шамин)

  • 1. Толстая модель История разработки ORM Шамин Михаил Geometria.ru Ведущий разработчик
  • 2.
  • 3. Geometria.ru • Главный фотохроникер страны • 8 лет на рынке • Представительство в 150 городах России, СНГ и Прибалтики • Ежедневно 80 000 пользователей / 600 000 просмотров • В понедельник 110 000 / 1 000 000 • Более 500 000 репортажей • 15 000 000 фотографий • 800 000 зарегистрированных пользователей
  • 4.
  • 5. Почему понадобился свой ORM Было • Наследство в виде залежей кода-лапши • Практически вся бизнес-логика в контроллерах • Вплоть до формирования select ов! • Некоторые экшены размером в 200 строк! • В роли модели - Zend_Db_Table
  • 6. Почему понадобился свой ORM Стало • Стали использовать NoSQL решения, такие как Redis и Mongo • Понадобилось решение, готовое работать с любым хранилищем, а не только SQL • Есть ли что-то на рынке? • Doctrine2 в alphа, еще сырая - страшно. • Что делать? • Пишем свой велосипед!
  • 7. Выбор дизайна Открываем книгу Мартина Фаулера (Martin Fowler) "Шаблоны корпоративных приложений" ("Patterns of Enterprise Application Architecture")
  • 8.
  • 9. Выбор дизайна И находим то что нужно. Domain Model или Модель предметной области
  • 10. Поля модели. Как задавать ? • В Zend_Db_Table_Row поля не прописаны явно, а берутся из схемы таблицы БД • В Doctrine2 через задание private/protected свойств и генерацию getter/setter методов.
  • 11. Поля модели. Решение: Использовать DocBlock Профиты: • Готовый шаблон для типов данных • Сразу в аннотации класса видны все поля модели • Автокомплит в IDE (Zend Studio, PhpStorm, NetBeans) • Быстрое создание классов
  • 12. Zend_Reflection для генерации полей /** * @property integer $id * @property string $title * @property string $body * @property boolean $hidden * @property integer $date **/ class Model_Post extends Geometria_Model { }
  • 13. Zend_Reflection для генерации полей После $post = new Model_Post(); свойство $_data будет выглядеть следующим образом: class Model_Post extends Geometria_Model { protected $_data = array( 'id' => null, 'title' => null, 'body' => null, 'hidden' => null, 'date' => null, ); }
  • 14. Доступ к полям • Внешний доступ к полям обеспечивается через магические методы __get() и __set() • Можно реализовать методы get<поле> и set<поле>, чтобы изменить логику установки/получения значения поля.
  • 15. /** * ... * @property integer $date Unix timestamp */ class Model_Post extends Geometria_Model ... public function setDate($value) { if ($value instanceof Zend_Date) { $value = $value->getTimestamp(); } $this->_data['date'] = $value; }
  • 16. Установка значения по умолчанию class Model_Post extends Geometria_Model ... public function getDate($value) { if (null === $this->_data['date']) { $this->_data['date'] = time(); } return $this->_data['date']; }
  • 17. Как хранить модель? Используем DataMapper • Маппер знает все о модели и о том, как и где еѐ хранить. • Модель ничего не знает о хранилище. • Логика домена отделена от persist логики • Можно менять структуру бд или даже сменить хранилище, не меняя логику модели, всего лишь изменив маппер. • Маппер выполняет CRUD операции • Можно использовать любое хранилище: MySQL, Mongo, Redis, Config file, RESTApi и др.
  • 18. Интерфейс маппера interface Geometria_Model_Mapper_Interface { public function create(Geometria_Model $model); public function update(Geometria_Model $model); public function delete(Geometria_Model $model); public function fetchOne($cond, $sort); public function fetchAll($cond, $sort, $limit, $skip); public function getCount($cond); }
  • 19. Работа с моделью $post = new Model_Post(); $post->title = 'hello world!'; $post->body = 'foo bar'; $postMapper = new Model_Post_Mapper(); $postMapper->create($post); echo $post->id; // 1 маппер сам проставил в модели id
  • 20. Выборки • Условие $cond - простой массив имя поля => значение • Сортировка $sort - тоже просто массив имя поля => (bool) направление сортировки • Для более сложных выборок пишем отдельный метод Выбрать 10 скрытых постов, начиная с самых новых $mapper->fetchAll( array('hidden' => true), array('date' => false), 10 );
  • 21. Делаем ActiveRecord Рассказываем модели, что у нее есть маппер. • Делаем статический метод getMapper() который из специального контейнера Geometria_Model_Mapper_Manager достает нужный ей маппер • Делаем у модели методы create(), update(), delete() public function create() { return self::getMapper()->create($this); }
  • 22. Теперь создание модели выглядит так: $post = new Model_Post(); $post->title = 'hello world!'; $post->body = 'foo bar'; $post->create(); echo $post->id; // 1 А пост можно получить в одну строчку: $post = Model_Post::getMapper()->fetchOne( array('id' => 1) ); или так $post = Model_Post::getMapper()->fetch(1);
  • 23. Что вернет fetchAll()? Коллекцию! • аналог Zend_Db_Table_Rowset • Паттерн Record Set • Позволяет выполнять массовые действия с набором моделей interface Geometria_Model_Collection_Interface extends Iterator, Countable { public function append(Geometria_Model $model); public function prepend(Geometria_Model $model); public function populate(array $data); public function clear(); public function toArray(); }
  • 24. Нужен Paginator? class Geometria_Paginator_Adapter_Mapper implements Zend_Paginator_Adapter_Interface { public function __construct( Geometria_Model_Mapper_Interface $mapper, array $cond = null, array $sort = null ) { $this->_mapper = $mapper; $this->_cond = $cond; $this->_sort = $sort; } }
  • 25. Нужен Paginator? class Geometria_Paginator_Adapter_Mapper ... public function getItems($offset, $limit) { return $this->_mapper->fetchAll( $this->_cond, $this->_sort, $limit, $offset ); } public function count() { return $this->_mapper->getCount( $this->_cond, $this->_sort ); }
  • 26. Хотим кешировать, логировать и тд. • Используем декоратор для маппера • Декортатор - это матрешка: в конструктор первого декоратора передаем маппер, в конструктор второго передаем первый декоратор и так далее • Декоратор перехватывает "интересующие" его методы, и изменяет результат на ему угодный, остальные методы просто пропускает дальше. • При инициализации маппера маппер-менеджер спрашивает у маппера, хочет ли он задекорироваться и оборачивает во все указанные декоратры
  • 27. Примеры декораторов Cache • fetchOne(), fetchAll() - на основании переданного условия берет данные из кеша, или же просит маппер выполнить запрос и кеширует его результат. • create(), update(), delete() - сбрасывает соответсвующий кеш. Profiler • Декоратор пропускает все запросы через себя, записывая в лог время выполнения запроса. Identity Map • Кеширует результаты в памяти, чтобы маппер не выполнял одинаковые запросы дважды
  • 28. Отношения Раз уж строим ORM, то должны быть отношения между сущностями. • Отношения так же, как и поля, задаются в DocBlock • Параметры описываются в спец формате • При создании модели, создаются объекты-менеджеры отношений • При обращении к полю, ссылающемуся на внешнюю сущность, объект-менеджер отношения делает запрос к внешнему мапперу и возвращает полученый объект.
  • 29. Пример работы с отношениями /** * ... * @property integer $authorId * @property Model_Author $author [relation=belongsTo;localKey=authorId] */ class Model_Post extends Geometria_Model {...} $post = Model_Post::getMapper()->fetchOne(array('authorId' => 5)); $author = $post->author; // Model_Author Менеджер отношения в данном случае выполнит запрос Model_Author::getMapper()->fetchOne(array('id' => 5));
  • 30. Виды отношений • hasOne - one-to-one отношение • belongsTo - тоже что и hasOne, но требует обязательного наличия объекта • hasMany - one-to-many отношение
  • 31. Полиморфические связи Обеспечивают связь с несколькими видами сущностей, то на какой тип сущности стоит ссылка определяет параметр ownerType, в то время как параметр ownerTypeId определяет id сущности. /** * @property string $ownerType * @property integer $ownerId * @property Model_User|Model_Post $owner [relation=polymorhic; localKey=ownerType; localTypeKey=ownerId] */ class Model_Comment extends Geometria_Model {..}
  • 32. Тонкости отношений $posts = Model_Post::getMapper()->fetchAll(); foreach ($posts as $post) { echo $post->title . ' by ' . $post->author; } Автор запрашивается при каждой итерации. Если у нас 10 постов, значит мы сделаем 1 запрос на получение постов и 10 запросов на получение авторов. Итого 11 запросов - плохо!
  • 33. Тонкости отношений Решение: $posts->fetchRelations('author'); Просим relation-manager получить всех авторов одним запросом и проставить во всех постах коллекции. Итого: 2 запроса, независимо от количества постов.
  • 34. Тонкости отношений А если у автора есть связь с картинкой-аватаркой? $posts->fetchRelations('author', 'picture'); Что означает, что перед тем, как "распихать" всех авторов по постам, у полученной коллекции авторов будет вызван метод: $authors->fetchRelations('picture');
  • 35. Каскадные операции У отношений можно прописать действие, которое будет выполняться при удалении модели onDelete: • CASCADE - удалить все связанные зависимые модели • SET NULL - очистить значения внешних ключей Это позволяет сохранять целостность связей внутри нашей системы.
  • 36. Жизнь без Join'ов Как сделать выборку постов, написанных женщинами, если посты используют одно хранилище, а авторы другое, и нет возможности сделать join? Использовать sphinx. • Создаем индекс в сфинксе для такого рода выборки. • Индексируем данные. • Создаем sphinx декоратор • Декоратор ищет id документов, удовлетворяющих поисковому запросу. И по этом списку id маппер возвращает коллекцию с результатом.
  • 37. Что дало внедрение ORM • Существенное ускорение разработки • Время вхождения в чужой код значительно уменьшилось • Использование Domain Driven Design позволяет говорить на языке предметной области, что повышает читаемость кода • Логика приложения вынесена в отдельный слой сервисов. Что позволяет использовать ее не только в MVC, но и в CLI, например. • Размер экшенов в контроллерах сократился до 10 строк.
  • 38. Будет ли open source? Будет, но позже )