Pull to refresh

Comments 54

И в итоге мы имеем не то сына не то дочь и не active record и не data mapper… Хотя к data mapper чуть ближе. Plain-old PHP объекты и Doctrine все-равно лучше. И это грустно ибо альтернативы вменяемой доктрине нет.
Блин, а я так надеялся увидеть что-то серьезное после ваших слов… Ну да, можно в доктрине инджектить ObjectManager в сущности явно. Клево. Никогда не использовал и не планирую. А для тех кто хотел бы там все же предупреждение написано.
Да в доктрине есть очень много интересного функционала, представленного исключительно в виде интерфейсов :)
Ну на самом деле это дальше ActiveRecord, просто разнесенный по классам. Кстати раз я уже тут добавлю еще вкусного, расскажу об наследовании.

В других ActiveRecord ORM приходиться наследовать саму модель. Это не очень удобно так как тогда в вашем классе сидит уйма логики от базы данных и это все потом надо мокать при тестировании. В PHPixie же наследование идет не от самих классов ОРМ а от спецыальних врапперов который проксюют все матоды в реальную ORM, упрощенно эти врапперы выглядят вот так:

class EntityWrapper implements EntityInterface {
     protected $entity;

     public function __construct($entity) {
           $this->entity = $entity;
     }

     public function save() {
          $this->entity->save();
     }
     //....etc
}

class FairyEntity extends EntityWrapper {

}


Таким образом вашы собственные классы не будут содержать никакой ОРМ логики а значит из будет очень легко тестировать. А также это означет что разработчики могут менять ОРМ внутри как хотят а ваш код все равно будет к этому устойчив
У нас аналогично устроено, только я разнес базовые объекты для ORM и ODM в разные компоненты. Функционал конечно похож (общий предок DataEntity присутствует), но и различий прилично.
Тьфу, перепутал про EntityWrapper, мне приходится наследоваться от модели т.к. в ней находятся необходимые мне валидации и фильтрации, а от базы там ровно три метода — delete, save и static find (возвращает Query как у вас). prntscr.com/6d8af9
Была одна клевая фича в вечноживом Пропеле. Очень клевая фича, которой не хватает многим ОРМам — кодогенерация запросов на основе колонок из БД. Например, запросы можно вызывать так:

$stellaQuery = $fairyRepository->query()
                    ->whereName('Stella');


методы whereXXXX генерятся на основе БД схемы. И потом их очень удобно использовать — легко писать код и намного меньше вероятность ошибиться при написании запросов. Было б неплохо, если б пикси такое умел )
Я так делал давным давно, но в один прекрасный момент (кол-во колонок) это стало больше мешать чем помогать — prntscr.com/6d6zqw (проект 4 летней давности).
Тогда бы проишлось или делать кодогенерацию ( чего очень хотелось избежать ) или каждый раз выбирать список колонок ( дополнительний запрос ). Конечно можно сделать отдельную либу которая сгенерит враппер классы для конкретной таблички основываясь на табличке. Хорошая идея =)
Да, опциональная кодогенерация, подключаемая как трейт в класс репозитория — хороший вариант
Зачем каждый раз? Для этого существует кэширование, например в YII 1 ORM была устроена именно так (не знаю насчет второй версии)
Однако, здравствуйте. (doctrine 2)
$oRepo = $oApp->getManagerRegistry()->getRepository('ORM\Entity\User');
$oQuery = $oRepo->createQueryBuilder('u')->getQuery();
Laravel так умеет делать) хотя я по привычке использую стандартный синтаксис.
Вот скажите, чем это лучше такого варианта?

$repository
    ->createQueryBuilder('f')
    ->where('f.name', 'Stella')
// ...
;


Читается лучше, в случае если есть джойны так же проще разобраться… Камелькейс не самая удобная штука для «пробежаться глазами и найти».
Ну какие-то преимущества есть, например для абстракции можно сделать интерфейс с методом whereName() и тогда даже если ОРМ не будет можно самому как-то этот метод имплементировать
Для репозитория — согласен, это удобно. Но для QueryBuilder — нет.
Что будет с любым ActiveRecord в случае если мы объект (к примеру User'а) ложим в Сессию. По логике связь с базой и вообще ORM прерывается, и после восстановления из базы у нас просто репрезентация данных, но(сразу дам пару костылей которые используют):
— К примеру нужно сделать правки в объекте восстановленном из сессии и мы их делаем, пытаемся вызвать save… и ошибка, нет связи.
1. Часто в Entity обратно получают подключение либо враппер через статические методы, превращая соединение в Signleton и блокируя возможность соединения с несколькими базами либо если хранится идентификатор это все равно не очень так как все равно нельзя явно это все переопределить.
2. Иногда с этой задачей справляются сами AuthenticationService либо SessionContainer, которые обратно при восстановлении инжектят нужные вещи внутрь той же Entity и мы получаем обратно работающий save. Но это очень костыльно, и не всегда можно точно определить откуда объект (к примеру в проекте у меня динамически увеличивается количество баз данных MongoDB под каждый «проект»).
— ActiveRecord обычно не хранят уже созданные Entity в каком-то UnitOfWork либо EntityPersister'е, поэтому очень часто при получении одного и той же записи мы получаем разные объекты, которые между собой не связаны, из-за этого возникают проблемы такие как: Мы обновляем текущего пользователя (полученного из запроса), но в сессии Юзер не обновился после привязки к менеджеру. Это решено достаточно хорошо в Data Mapper'ах где вместо оригинальной Entity часто отдает проксю, котора тянет данные не из реальной репрезентации а их общего хранилища оригиналов (__initializer__ в Doctrine который обращается к EntityPersister'у и берет оттуда данные). Что в данном случае у ActiveRecord:
1. Есть пару попыток реализации кеша этих самых Entity, но часто они сделаны не совсем гибко: отдается один и тот же объект, но есть проблема с случайным обновлением, которое еще не заперсистили, но мы уже везде его видим.

Времени мало, но таких «особенностей» можно описать очень много, я сам являюсь контрибьютором в Doctrine, и пишу собственную легковесную ORM совместимую с Doctrine но лишенную многих вещей влияющих на скорость.
Ложыть в сессию всего юзера это уже антипаттерн сам по себе:

  • Дамп всего объекта займет много места в сериализированном виде. Если таких сессий штук 10000 очень даже ощутимо
  • Оверхед десериаоизвции такой сессии также заметен. Особенно если из этого объекта наи ничего не нужно ( например просто проверям залогинен ли юзер
  • Имхо лучше просто хранить айди в сессии и все
+ проблема инвалидации данных юзера (сессий же может быть несколько)
Так зачем еще и блог свой писать и форум ?) Время то не резиновое
Ну это своего рода показывает уровень доверия к фреймворку. В целом я не вижу в этом ничего плохого… разве что для этого блога и сайта в целом можно было взять какой-нибудь генератор статических сайтов вроде sculpin или phrozn.
>> Так зачем еще и блог свой писать и форум ?) Время то не резиновое

Хорошо, блог и форум сделали на вордпрессе. Ну на остальные 2,5 html-странички (homepage, документация) можно было и найти время.
Так а зачем мне фреймворк для HTML странички? =))
А документация сгенерена apigen-ом

Ну я вам обещаю что что-что а HTML фреймворк точно вывести осилит =)
>> Так а зачем мне фреймворк для HTML странички? =))

У вас не написано, для какого рода проектов создан фреймворк, поэтому считаем, что для создания простеньких HTML страничек в том числе он и создан. А теперь вопрос: зачем мне его использовать для сайтов, если вы его сами не используете?)
Ну кто сказал что не использую, просто не для блога и документации которые и так из коробки работают =)
Повсюду где я работал мы всегда к нему приходили, кстати на гитхабе порядка 1200 проектов его используют: github.com/search?utf8=%E2%9C%93&q=class+Pixie+extends+%5CPHPixie%5CPixie&type=Code&ref=searchresults
хабр — такой хабр ) за что минус?)
Потому что хабр такой хабр. Подобные вещи стоит сообщать в личку. Как минимум потому что после исправление подобные комменатрии выглядят глупо и не информативно.
Бенчмарки будут всего фрейсворка когда буду закончены оставшеися компоненты. Можно посмотреть бенчмарки предидущей версии на www.techempower.com/benchmarks/
По примерам — это DBAL, а не ORM.
Почему-же? В DBAL нет связей между сущностями, это и есть отличительная черта ОРМ ( Object-relational mapping )
Пардон, у меня сегодня глаза на заднице.
Что вам помешало допилить автоматическое создание таблиц в БД и синхронизацию структуры?
Идеология =) Такие действия будет выполнять компнент миграции
Компонент миграции только в планах, или уже можно использовать?
Очень интересная Orm, а вот если предположить, что у нас не цветок, как уникальная единица, а тип цветка с множеством свойств, тогда на уровне БД нам понадобится связь многие-ко-многим, по сути нужна таблица связки, и вопрос в том, сколько потребуется orm запросов, чтобы вывести все цветочки у какой либо феи, ну и наоборот у цветочка, посмотреть, каким феям он интересен, тоже один?
многие-ко-многим тоже получаются в один запрос =)
Скажите, что ещё и индексы сами проставляются, и я побегу использовать его в каком нибудь проекте:)
Таблицы автоматически не создаются, для этого потом будет модулт миграции
Вы наверное внешние ключи имеете ввиду?
Несколько месяцев назад читал про ваш фремворк. И ORMка очень понравилась.
Однако, тогда подумал, что разработка мертва. Рад, что ошибся, надо будет попробовать с чем-нибудь «для души».
Кстати да, сейчас присматриваюсь к выбору фраемворка и начал акцентрировать свое внимание на Pixie. Честно говоря что-то меня уже спугнуло. Но поделиться основным пугающем фактором все-таки решусь. Основная ветка github.com/dracony/PHPixie обновлялась год назад. Что создает иллюзию заброшенности. Хотя если зайти в профиль dracony, то будет видно. Что по сегодняшний день появляются новые коммиты относительно Pixie, но уже для модулей.
github.com/dracony/PHPixie это просто дефолтный проект, в котром подтягиваются все зависимости и запускается само приложение, там собственно нечего обновлять. Все разбито по компонентам.

Компоненты 3-й версии находятся тут: github.com/phpixie/ но она еще не закончена полностью
Sign up to leave a comment.

Articles