Как использовать пользовательские функции DQL в partials для гидратации результата запроса.
Ищете способ использовать функции DQL в createQuery или любом другом доктрине (nativeSql, QueryBuilder), не обязательно использовать частичные, но он должен увлажнять мой массив на основе отношения таблиц, и он должен выбирать только выборочные поля
После выполнения запросов работает нормально:
$q = $em->createQuery("select " . "partial t.{id, description}, " . "partial ut.{id, firstName, lastName, email}, " . "DATE_FORMAT(ut.created, '%m-%d-Y') " . "from PMIUserBundle:Task t LEFT JOIN t.users ut");
DATE_FORMAT (ut.created, '% m-% d-Y') отлично работает, когда его из частичного.
DATE_FORMAT
уже зарегистрирован как пользовательская функция в config.yml
config.yml:
dql: datetime_functions: DATE_FORMAT: PMI\UserBundle\DoctrineFunctions\DateFormat
Следующий запрос создает проблему:
$q = $em->createQuery("select " . "partial t.{id, description}, " . "partial ut.{id, firstName, lastName, email, DATE_FORMAT(created, '%m-%d-Y')}, " . "DATE_FORMAT(ut.created, '%m-%d-Y') " . "from PMIUserBundle:Task t LEFT JOIN t.users ut");
дает ошибку:
[Syntax Error] line 0, col 91: Error: Expected Doctrine\ORM\Query\Lexer::T_CLOSE_CURLY_BRACE, got '('
Ниже приведен мой класс DateFormat:
class DateFormat extends \Doctrine\ORM\Query\AST\Functions\FunctionNode { protected $dateExpression; protected $formatChar; public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) { return 'DATE_FORMAT('. $sqlWalker->walkArithmeticExpression($this->dateExpression) . ','. $sqlWalker->walkStringPrimary($this->formatChar). ')'; } public function parse(\Doctrine\ORM\Query\Parser $parser) { $parser->match(Lexer::T_IDENTIFIER); $parser->match(Lexer::T_OPEN_PARENTHESIS); $this->dateExpression = $parser->ArithmeticExpression(); $parser->match(Lexer::T_COMMA); $this->formatChar = $parser->StringPrimary(); $parser->match(Lexer::T_CLOSE_PARENTHESIS); } }
РЕДАКТИРОВАТЬ:
Хорошо, поэтому Partial не позволит мне использовать функции DQL. Благодаря FuzzyTree для решения использовать ut->getFormattedCreatedDate()
внутри моего класса сущности. Но мне все же интересно, что если мы группируем дочернюю таблицу и вычисляем некоторую сумму, используя функции mysql Aggregate.
Как достичь следующих критериев в doctrine2 с помощью createQuery, queryBuilder, nativeSQl или любым другим способом:
каждый раз, если мы используем функции DQL, нужно ли создавать классы для таких, как я создал для DateFormat? что, если мы используем вложенные функции MySql, такие как
GROUP_CONCAT(DISTINCT CONCAT(tags.id,',',tags.displayName)
Спасибо, что прочитал мой вопрос.
Как использовать пользовательские функции DQL в partials для гидратации результата запроса.
partial
ключевое слово указывает доктрине возвращать объекты, которые только частично гидратируются, и позволяет указать, какие поля вы хотите увлажнить.
При извлечении частичных сущностей вы ограничены выбором полей объекта (потому что в противном случае, где бы учение «хранилище» выбранного вами поля?), Поэтому невозможно указать функцию DQL как поле частичного объекта.
Как насчет этого?
$qb = $this->_em->createQueryBuilder() ->select( 't.id, t.description, ' . 'ut.id, ut.firstName, ' . 'ut.lastName, ut.email, ' . 'DATE_FORMAT( ut.created, \'%m-%dY\' )' ) ->from( 'PMIUserBundle:Task', 't' ) ->leftjoin( 't.users', 'ut' ); $result = $qb->getQuery()->getResult();
Предполагая, что вы используете это в классе Repository (вот почему вызов $ this -> _ em).
Я заметил еще 2 вещи относительно пользовательской функции:
Надеюсь это поможет,
Tam
PARTIAL ut.{id, firstName, lastName, email, DATE_FORMAT(created, '%m-%d-Y')}
Использование DQL-функций внутри выделения частичных объектов, подобных этому, не поддерживается.
Это тоже не имеет особого смысла. В этом случае вы (вероятно) сопоставили поле, created
как поле datetime
, поэтому вы ожидаете полного значения DateTime
. Но теперь вы просто используете часть даты. И все хуже: вы отформатировали значение таким образом, чтобы объект DateTime
не мог быть создан (он ожидает Ymd H:i:s
, а тип date
ожидает Ymd
).
Для любого частичного выбора: вы не можете и не должны изменять значение поля.
Вместо того, чтобы увлажнять частичные объекты, вы можете просто использовать массивы. Используйте $q->getArrayResult()
или $q->getScalarResult()
, что лучше подходит для вашей цели.
Если хотите, вы можете группировать / вставлять результаты в метод репозитория. Пример:
public function getSomeData() { $result = array(); $dql = <<<EOQ SELECT t.id AS t_id, t.description AS t_description, u.id AS u_id, u.firstName AS u_firstName, u.lastName AS u_lastName, u.email AS u_email, DATE_FORMAT(u.created, '%m-%d-Y') AS u_created FROM PMIUserBundle:Task t LEFT JOIN t.users u EOQ; $q = $this->getEntityManager()->createQuery($dql); foreach ($q->getScalarResult() as $row) { if (!isset($result[$row['t_id']])) { $result[$row['t_id']] = array( 'id' => $row['t_id'], 'description' => $row['t_description'], 'users' => array() ); $result[$row['t_id']]['users'][] = array( 'u.id' => $row['u_id'], 'u.firstName' => $row['u_firstName'], 'u.lastName' => $row['u_lastName'], 'u.email' => $row['u_email'], 'u.created' => $row['u_created'] ); } } return $result; }
Вложенные функции DQL не должны быть проблемой (если вы написали их правильно). И DISTINCT
поддерживается из коробки.