Комментарии 36
Спасибо, очень полезная статья: на официальном сайте doctrine про бихэйвиоры не густо, а на просторах интернета из полезных статей могу выделить разве что это:
clear-cache.fr/?post/2009/11/26/How-to-create-a-custom-Doctrine-behavior
clear-cache.fr/?post/2009/11/26/How-to-create-a-custom-Doctrine-behavior
Не знаю, не знаю. Тоже с выходом 1.3-1.4 решил попробовать doctrine на одном небольшом проекте. Поначалу шло нормально, но когда пошла какая-то разумная логика, долго пытался вникнуть, как это сделать в doctrine. Behavior'ы (например, geo) или декораторы в propel делаются тоже несложно, а код как-то более читабельным мне видится. Общее впечатление: doctrine недоработана, чувствуется какая-то сырость.
Впрочем, использование той или иной ORM больше дело вкуса.
Впрочем, использование той или иной ORM больше дело вкуса.
В основном, претензии были к мелочам. Например, я сразу не сумел подключить getter'ы для доступа к свойствам объекта. Давайте я вкратце опишу сам проект и по этапам возникшие сложности:
1. Использовалось 8 таблиц в БД. 3 связи many-to-many, около 8 — one-to-many. Практически все объекты были timestamtable + 3 объекта — geo (latitude, longitude).
На уровне написания yaml-файла проблем не возникло. Синтаксис propel мне нравился больше, но это — дело вкуса.
2. Далее, система представляла собой серверную часть мобильного клиента. Поэтому один и тот же набор данных зачастую должен был быть по-разному представлен. При этом представления вполне могли поменяться. Нецелесообразно было делать под каждый конкретный запрос template, поэтому было принято решение написать небольшой декоратор и внедрить его в генерацию. Для propel я это делал в предыдущем проекте и нагуглил очень быстро решение. Для doctrine пришлось вдумчиво медитировать и пробовать варианты.
3. Я так в итоге и не понял, как, например, с помощью DQL + прочего получить выборку объектов, удовлетворяющих определённому условию, и удалить их через связь один-многие-(многие-которые-с-условием). Пришлось разбивать на подзапросы, полез «говнокод». Кстати, совершенно не понял логику DQL — зачем мне извращаться с select и прочими методами, когда, по сути, можно написать такой же SQL. К чему сложности?
Делал я в итоге этот проект около 1.5 месяцев, впечатления остались неприятные. Я так и не понял основную логику Doctrine, возможно, потому что мало с ней работал. Но propel-подход мне кажется более строгим и потому понятным.
1. Использовалось 8 таблиц в БД. 3 связи many-to-many, около 8 — one-to-many. Практически все объекты были timestamtable + 3 объекта — geo (latitude, longitude).
На уровне написания yaml-файла проблем не возникло. Синтаксис propel мне нравился больше, но это — дело вкуса.
2. Далее, система представляла собой серверную часть мобильного клиента. Поэтому один и тот же набор данных зачастую должен был быть по-разному представлен. При этом представления вполне могли поменяться. Нецелесообразно было делать под каждый конкретный запрос template, поэтому было принято решение написать небольшой декоратор и внедрить его в генерацию. Для propel я это делал в предыдущем проекте и нагуглил очень быстро решение. Для doctrine пришлось вдумчиво медитировать и пробовать варианты.
3. Я так в итоге и не понял, как, например, с помощью DQL + прочего получить выборку объектов, удовлетворяющих определённому условию, и удалить их через связь один-многие-(многие-которые-с-условием). Пришлось разбивать на подзапросы, полез «говнокод». Кстати, совершенно не понял логику DQL — зачем мне извращаться с select и прочими методами, когда, по сути, можно написать такой же SQL. К чему сложности?
Делал я в итоге этот проект около 1.5 месяцев, впечатления остались неприятные. Я так и не понял основную логику Doctrine, возможно, потому что мало с ней работал. Но propel-подход мне кажется более строгим и потому понятным.
Делал, выбирал, в чём вопрос? В оптимизации? В удобстве? По мне подобные сложные задачи можно спокойно разбить на подзадачи и подзапросы.
М-да, у меня такие же сложности возникали в обратной ситуации, я собирал идентификаторы в Doctrine, чтобы потом удалить нужные записи.
Касательно propel:
1. Метод «в лоб»
foreach ($posts as $post)
{
$comments = $post->getComments();
foreach ($comments as $comment)
{
/** do smth with comment */
// echo $comment->getUser();
}
}
Оптимизация? Здравствуй, memcached и пр., если проект предполагает быть нагруженным.
2. raw sql query
Никто не отменял. Более того, код, который Вы написали в Doctrine, по сути, то же самое.
3. А кто мешает сделать то же самое, что и в Doctrine, с помощью Criteria? Не увидел разницы.
Касательно propel:
1. Метод «в лоб»
foreach ($posts as $post)
{
$comments = $post->getComments();
foreach ($comments as $comment)
{
/** do smth with comment */
// echo $comment->getUser();
}
}
Оптимизация? Здравствуй, memcached и пр., если проект предполагает быть нагруженным.
2. raw sql query
Никто не отменял. Более того, код, который Вы написали в Doctrine, по сути, то же самое.
3. А кто мешает сделать то же самое, что и в Doctrine, с помощью Criteria? Не увидел разницы.
вроде как это делается при помощи Doctrine_Collection::synchronizeWithArray(). хотя лично я, к своему стыду, этим методом не пользовался.
Вах, не видел, не слышал, надо погуглить.
1. Здесь всё зависит от задачи. В моём случае в распоряжении был VDS + менее 5000 юзеров в день (максимальная нагрузка как раз 5К). Соответственно, нафига козе баян? Дайте реальные условия — будем модифицировать. Первое решение «в лоб» приходит на ум сразу, оно красиво и понятно написано, легко поддерживаемо.
2. Ну, батенька, не скажите, это уже дело вкуса, как написать так, чтобы было поддерживаемо. Код doctrine в данном конкретном случае короче, но по сути делает и выглядит также.
3. Давайте тогда сформулируйте конкретную задачу, покажите соответствующий код на doctrine, а я сделаю на propel через criteria, сравним.
Ой нее, вы что такой код писать, где в цикле еще запрос в базу данных, а то и не один запрос. Не наш метод. Мой насяльника, как и насяльника develop7 просто запрещает делать такие вещи (хотя на работе к php я не имею вообще никакого отношения, у нас ColdFusion).
В Доктрине я бы написал один запрос в базу, отсортировал правильно, и выводил бы в одном foreach абсолютно всю информацию которую надо. Не знаю на сколько это правильно, но запросов к БД становится на порядок меньше.
В Доктрине я бы написал один запрос в базу, отсортировал правильно, и выводил бы в одном foreach абсолютно всю информацию которую надо. Не знаю на сколько это правильно, но запросов к БД становится на порядок меньше.
Писать сложные запросы на DQL куда как легче, прозрачней и понятней чем на Propel. На Propel у меня уже возникали трудности при выборке из 3-х (насколько помню) таблиц. Сейчас же, с Доктриной, сложные выборки — идут просто как семечки.
На ваш вопрос «совершенно не понял логику DQL — зачем мне извращаться с select и прочими методами, когда, по сути, можно написать такой же SQL. К чему сложности?» в комментарии выше.
Это сделано для того, чтобы сделать ваш проект независимым от базы данных. Вы сможете с легкостью разрабатывать под MySQL, но заказчик скажет «Не-а, хочу MSSQL», и вы в одно мгновение переключаете разработку с одной базы данных на другую. (или я где-то не так понял ваш вопрос?)
На ваш вопрос «совершенно не понял логику DQL — зачем мне извращаться с select и прочими методами, когда, по сути, можно написать такой же SQL. К чему сложности?» в комментарии выше.
Это сделано для того, чтобы сделать ваш проект независимым от базы данных. Вы сможете с легкостью разрабатывать под MySQL, но заказчик скажет «Не-а, хочу MSSQL», и вы в одно мгновение переключаете разработку с одной базы данных на другую. (или я где-то не так понял ваш вопрос?)
Гм, я был бы благодарен за пример. Возможно, судьба была милостива ко мне и не давала подобные запросы. Могу сказать одно — при небольшой-средней нагрузке с кэшированием результатов проблем с подобными циклами у меня не возникало. Я понимаю, что это не есть true, поэтому обычно делаю через Criteria.
Касательно смены БД — ей Богу, сколько проектов не делал, в том числе один весьма жирный, ни разу не меняли тип БД. Да и кому оно надо? Это, скорее, плюс из разряда «неплохо было бы».
Касательно смены БД — ей Богу, сколько проектов не делал, в том числе один весьма жирный, ни разу не меняли тип БД. Да и кому оно надо? Это, скорее, плюс из разряда «неплохо было бы».
В поставке sf 1.4 propel 1.4
kill the magic!
kill the magic!
Пока я не чувствую особой разницы, если честно, между Propel'ом и Doctrine. Стоит сказать, что Propel работает у меня на нескольких проектах, а Doctrine я начал использовать на проекте, который ещё не запущен.
Посмотрим результаты в боевой среде =)
Посмотрим результаты в боевой среде =)
Да, было бы интересно посмотреть в реальной обстановке на скорость работы, на время, которое тратится на рефакторинг / разработку нового функционала. Пока что на тех проектах, которые я делал, разницы не наблюдается по скорости (и то, и то работает достаточно быстро). Допиливать мне было проще propel. Посмотрим, как будет у Вас.
Коллега, а Вы не хотите сделать доклад на РИТ++ (http://www.ritconf.ru/)?
Если интересно, то я могу выслать подробную информацию.
Если интересно, то я могу выслать подробную информацию.
Спасибо за статью, очень познавательно. Забыли упомянуть, что плагин нужно добавить в config/ProjectConfiguration.class.php, чтобы symfony его увидела.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Doctrine Behavior на примере собственного плагина