Funções DQL personalizadas na doctrine2

Como você usa funções DQL personalizadas em parciais para hidratar o resultado da consulta.

Procurando uma maneira de usar as funções do DQL em createQuery ou qualquer outra maneira de doctrine (nativeSql, QueryBuilder), não é necessário usar partials, mas deve hidratar minha matriz com base na relação de tabelas e deve selecionar apenas campos seletivos

A consulta seguinte funciona bem:

$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’) funciona bem quando está fora de parcial.

DATE_FORMAT já está registrado como function personalizada em config.yml

config.yml:

 dql: datetime_functions: DATE_FORMAT: PMI\UserBundle\DoctrineFunctions\DateFormat 

A consulta a seguir cria o problema:

  $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"); 

dá erro:

 [Syntax Error] line 0, col 91: Error: Expected Doctrine\ORM\Query\Lexer::T_CLOSE_CURLY_BRACE, got '(' 

A seguir é minha class 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); } } 

EDITAR:

Ok, então Parcial não me permitirá usar funções DQL. Graças a FuzzyTree para a solução usar ut->getFormattedCreatedDate() dentro da minha class de entidade. Mas ainda estou curioso se formos agrupando a tabela infantil e calculando alguma quantidade usando as funções de agregação do mysql.

Como alcançar os seguintes critérios em doctrine2 usando createQuery, queryBuilder, nativeSQl ou qualquer outra maneira:

  1. Selecione apenas os campos seletivos
  2. Agrupar por entidade de tabela filho usando Funções Agregadas
  3. Hydrate array com base nas relações de tabela, os resultados das funções agregadas devem estar na matriz filho.

sempre que usamos funções DQL, temos que criar classs para isso como eu criei para DateFormat? e se nós estivermos usando funções MySQL MySQL como

 GROUP_CONCAT(DISTINCT CONCAT(tags.id,',',tags.displayName) 

Obrigado por ler minha pergunta.

Como você usa funções DQL personalizadas em parciais para hidratar o resultado da consulta.

A palavra-chave partial diz a doctrine para retornar entidades que são apenas parcialmente hidratadas e permite que você especifique quais os campos que deseja hidratar.

Ao recuperar entidades parciais, você está limitado a selecionar os campos da entidade (porque de outra forma, onde a doctrine “armazene” o campo que você está selecionando?), Portanto, não é possível especificar uma function DQL como um campo de um object parcial.

E quanto a isso?

  $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(); 

Supondo que você esteja usando isso em uma class Repositório (é por isso que a chamada para $ this -> _ em).

Tenho notado 2 outras coisas relacionadas à function personalizada:

  1. Eu pessoalmente, ele definiu como um “string_functions:” em vez do arquivo config.yml
  2. Conheço pelo menos um pacote que implementa essa function personalizada: https://github.com/beberlei/DoctrineExtensions

Espero que isto ajude,

Tam

Não suportado

 PARTIAL ut.{id, firstName, lastName, email, DATE_FORMAT(created, '%m-%d-Y')} 

O uso de funções DQL dentro da seleção de entidades parciais como esta não é suportado.

Também não faz muito sentido. Nesse caso, você (provavelmente) mapeou o campo created como um campo de datetime e datetime , então você esperará um valor de DateTime completo lá. Mas agora você está apenas usando a parte da data. E piora: você formatou o valor de tal forma que um object DateTime não pode ser criado (espera Ymd H:i:s e o tipo de date espera Ymd ).

Para qualquer seleção parcial: você não pode , e não deve , alterar o valor de um campo.

Alternativa

Em vez de se hidratar em entidades parciais, você poderia usar arrays. Use $q->getArrayResult() ou $q->getScalarResult() , o que se adequar melhor a sua finalidade.

Se você quiser, você pode agrupar / aninhar os resultados no método Repositório. Exemplo:

 public function getSomeData() { $result = array(); $dql = < <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; } 

Aninhando funções DQL

As funções de Nesting DQL não devem ser problema (se você as escreveu corretamente). E DISTINCT é suportado fora da checkbox.