Довольно давно использую связку Zend Framework и Doctrine и очень не хватало сортировки для коллекций получаемых по ссылке. Оказалось, что это легко реализовать.
Позже в одном из проектов, созданном компанией в которой я работаю, был найден подобный метод, но, увы, не ясно просочилось-ли это от разработчиков Doctrine или было создано в недрах моей команды. Смущает тот факт, что найденный фрагмент кода написан для СУБД, которая в нашей компании не используется.
Все манипуляции производились на версии 1.1.3, но должны принести плоды и при использовании более ранних версий Doctrine.
Метод заключается в правке единственного файла. Да, внесение модификаций в код сторонней библиотеки не есть гуд, но, к сожалению, на данный момент другого выхода не видно. Или я плохо искал?
Открываем файл Doctrine/Relation.php и находим место описания массива определений:
Добавляем еще одну пару ключ/значение:
Это необходимо по причине того, что Doctrine именно на базе этого массива составляет список передаваемых в свои классы определений, указанных при формировании связей.
Находим определение функции getRelationDql и добавляем туда код для реализации сортировки. Таким образом функция будет иметь следующий вид:
Т.е. мы указываем необходимость сортировки в случае, если это определено в описании связи. Именно в этом фрагменте кода ORDER BY может принимать другие формы для разных диалектов SQL.
Осталось в определении связи задать сортировку:
Таким образом происходит сортировка коллекций для связи многие к одному, что и требовалось получить. Надеюсь, что статья будет кому-то полезна.
Позже в одном из проектов, созданном компанией в которой я работаю, был найден подобный метод, но, увы, не ясно просочилось-ли это от разработчиков Doctrine или было создано в недрах моей команды. Смущает тот факт, что найденный фрагмент кода написан для СУБД, которая в нашей компании не используется.
Все манипуляции производились на версии 1.1.3, но должны принести плоды и при использовании более ранних версий Doctrine.
Метод заключается в правке единственного файла. Да, внесение модификаций в код сторонней библиотеки не есть гуд, но, к сожалению, на данный момент другого выхода не видно. Или я плохо искал?
Открываем файл Doctrine/Relation.php и находим место описания массива определений:
protected $definition = array(… );
Добавляем еще одну пару ключ/значение:
'order' => null,
Это необходимо по причине того, что Doctrine именно на базе этого массива составляет список передаваемых в свои классы определений, указанных при формировании связей.
Находим определение функции getRelationDql и добавляем туда код для реализации сортировки. Таким образом функция будет иметь следующий вид:
public function getRelationDql($count) { $component = $this->getTable()->getComponentName(); $dql = 'FROM ' . $component . ' WHERE ' . $component . '.' . $this->definition['foreign'] . ' IN (' . substr(str_repeat('?, ', $count), 0, -2) . ')'; if (!empty($this->definition['order'])) { $dql .= ' ORDER BY ' . $this->definition['order']; } return $dql; }
Т.е. мы указываем необходимость сортировки в случае, если это определено в описании связи. Именно в этом фрагменте кода ORDER BY может принимать другие формы для разных диалектов SQL.
Осталось в определении связи задать сортировку:
$this->hasMany('Products', array('local'=>'id','foreign'=>'category_id', 'order'=>'position desc'));
Таким образом происходит сортировка коллекций для связи многие к одному, что и требовалось получить. Надеюсь, что статья будет кому-то полезна.