Как стать автором
Обновить

Комментарии 36

Может и не густо, но на мой взгляд вполне достаточно.
Там, вроде как, нет ничего про генераторы.
Ну, да. Чего нет, того нет. Хотя есть исходники стандартных.
Ну так значит мой топик всё же имеет право на жизнь.
А я и не спорю.
*стандартных шаблонов
Для propel, впрочем, тоже информация «раскидана» по интернетам. Так что здесь, ИМХО, ничья.
Лично у меня было куда меньше проблем с написанием бихэйвиоров на пропеле — не знаю почему.
Когда я искал, как создать behaviour в propel, я нашёл ответ в каком-то левом блоге.
Ага. А вы юзеру добавляли relation [ComponentName]Votes?
Я — нет, так как пользователи по неподвластным мне причинам находятся в другой базе, соответственно связь между полями построить нельзя. Вам, я надеюсь, ничего не помешает это сделать самостоятельно.
Не знаю, не знаю. Тоже с выходом 1.3-1.4 решил попробовать doctrine на одном небольшом проекте. Поначалу шло нормально, но когда пошла какая-то разумная логика, долго пытался вникнуть, как это сделать в doctrine. Behavior'ы (например, geo) или декораторы в propel делаются тоже несложно, а код как-то более читабельным мне видится. Общее впечатление: doctrine недоработана, чувствуется какая-то сырость.

Впрочем, использование той или иной ORM больше дело вкуса.
Что конкретно вы хотели сделать, используя Doctrine, и как вы пытались это сделать?
В основном, претензии были к мелочам. Например, я сразу не сумел подключить 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-подход мне кажется более строгим и потому понятным.
Впрочем, использование той или иной ORM больше дело вкуса.
Слабое оправдание.
В поставку symfony 1.3/1.4 входит, насколько я знаю, Propel 1.3. Будете выбирать им, скажем, посты+комментарии+авторов постов и комментариев — обязательно отпишитесь, когда всё закончится. Сравним впечатления.
Делал, выбирал, в чём вопрос? В оптимизации? В удобстве? По мне подобные сложные задачи можно спокойно разбить на подзадачи и подзапросы.
Дада, я тоже. Propel 1.3: doSelectPostsJoinComments; foreach по постам и комментам постов; собрал user_id; сложил в разные массивы; doSelectByPks($ids); foreach по результату; рассовал юзеров по постам и комментам (setUser($user)). Просто! Прозрачно! Удобно! Не то, что Doctrine_Query::create()->from('Post p, p.Owner po, p.Comments pc, pc.Owner pco')->execute()

И это я ещё неудачный пример привёл. Лично я вручную джойнил Event + sfGuardUserProfile + sfGuardUser. Делалось это так. Скопипастил BaseEventPeer::doSelectJoinSfGuardUser(); прошёлся по исходному resultsetу, выдрал user_id; запросом собрал sfGuardUserов; распихал их по профайлам.
М-да, у меня такие же сложности возникали в обратной ситуации, я собирал идентификаторы в 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? Не увидел разницы.
собирал идентификаторы в Doctrine, чтобы потом удалить нужные записи
вроде как это делается при помощи Doctrine_Collection::synchronizeWithArray(). хотя лично я, к своему стыду, этим методом не пользовался.

1. И post_count + total_comment_count запросов к БД. Тогдашний насяльника мне за такое говорил «Ай-яй-яй, нехорошо так делать. Перепиши, ладно?».
2. и гидрация руками. И никакая reusability полученного кода (кроме copy'n'paste). Извините, я слишком ленив.
код, который Вы написали в Doctrine, по сути, то же самое
я какбы намекаю, что код doctrine короче. Существенно. А следовательно, легче поддерживается.
3. можно код в студию?
вроде как это делается при помощи Doctrine_Collection::synchronizeWithArray(). хотя лично я, к своему стыду, этим методом не пользовался.


Вах, не видел, не слышал, надо погуглить.

1. Здесь всё зависит от задачи. В моём случае в распоряжении был VDS + менее 5000 юзеров в день (максимальная нагрузка как раз 5К). Соответственно, нафига козе баян? Дайте реальные условия — будем модифицировать. Первое решение «в лоб» приходит на ум сразу, оно красиво и понятно написано, легко поддерживаемо.

2. Ну, батенька, не скажите, это уже дело вкуса, как написать так, чтобы было поддерживаемо. Код doctrine в данном конкретном случае короче, но по сути делает и выглядит также.

3. Давайте тогда сформулируйте конкретную задачу, покажите соответствующий код на doctrine, а я сделаю на propel через criteria, сравним.
надо погуглить
Зачем гуглить, когда есть исходники?
Из серии «зачем гуглить, когда есть man»? В Гугле есть шанс найти пару статей, в которых автор сталкивался с идентичными проблемами и написал краткий how-to, где всё разжёвано.
Экономия времени?
Ой нее, вы что такой код писать, где в цикле еще запрос в базу данных, а то и не один запрос. Не наш метод. Мой насяльника, как и насяльника develop7 просто запрещает делать такие вещи (хотя на работе к php я не имею вообще никакого отношения, у нас ColdFusion).

В Доктрине я бы написал один запрос в базу, отсортировал правильно, и выводил бы в одном foreach абсолютно всю информацию которую надо. Не знаю на сколько это правильно, но запросов к БД становится на порядок меньше.
Писать сложные запросы на DQL куда как легче, прозрачней и понятней чем на Propel. На Propel у меня уже возникали трудности при выборке из 3-х (насколько помню) таблиц. Сейчас же, с Доктриной, сложные выборки — идут просто как семечки.

На ваш вопрос «совершенно не понял логику DQL — зачем мне извращаться с select и прочими методами, когда, по сути, можно написать такой же SQL. К чему сложности?» в комментарии выше.
Это сделано для того, чтобы сделать ваш проект независимым от базы данных. Вы сможете с легкостью разрабатывать под MySQL, но заказчик скажет «Не-а, хочу MSSQL», и вы в одно мгновение переключаете разработку с одной базы данных на другую. (или я где-то не так понял ваш вопрос?)
Гм, я был бы благодарен за пример. Возможно, судьба была милостива ко мне и не давала подобные запросы. Могу сказать одно — при небольшой-средней нагрузке с кэшированием результатов проблем с подобными циклами у меня не возникало. Я понимаю, что это не есть true, поэтому обычно делаю через Criteria.

Касательно смены БД — ей Богу, сколько проектов не делал, в том числе один весьма жирный, ни разу не меняли тип БД. Да и кому оно надо? Это, скорее, плюс из разряда «неплохо было бы».
пример навскидку — бд в sqlite::memory для функциональных тестов.
В поставке sf 1.4 propel 1.4
kill the magic!
Не знал. И как, с Propel 1.4 подобные задачки проще делаются?
Там есть такая конструкция: $c->addMultipleJoin(array-of-arrays-of-fields). Соответственно, тип join'а определяете сами через константы Criteria.
Пока я не чувствую особой разницы, если честно, между Propel'ом и Doctrine. Стоит сказать, что Propel работает у меня на нескольких проектах, а Doctrine я начал использовать на проекте, который ещё не запущен.

Посмотрим результаты в боевой среде =)
Да, было бы интересно посмотреть в реальной обстановке на скорость работы, на время, которое тратится на рефакторинг / разработку нового функционала. Пока что на тех проектах, которые я делал, разницы не наблюдается по скорости (и то, и то работает достаточно быстро). Допиливать мне было проще propel. Посмотрим, как будет у Вас.
Коллега, а Вы не хотите сделать доклад на РИТ++ (http://www.ritconf.ru/)?
Если интересно, то я могу выслать подробную информацию.
Да, почему бы и нет? Жду подробной информации.
Спасибо за статью, очень познавательно. Забыли упомянуть, что плагин нужно добавить в config/ProjectConfiguration.class.php, чтобы symfony его увидела.
Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.