Um dos ganhos de performance do Doctrine2 é devido a sua DQL conter apenas as funções que são comuns a todos os bancos de dados.
Para utilizarmos funções específicas de cada banco de dados (por exemplo, a função IFNULL
do MySQL ou a função NVL
do Oracle), o Doctrine nos permite adicioná-las através de extensões.
Segue aqui um exemplo para adicionar uma função YEAR
, que retorna o ano de uma data fornecida, utilizando a função EXTRACT
do Oracle:
Primeiro adicione um diretório que irá conter a sua função, por exemplo DoctrineExtensions\Query\Oracle
.
Dentro deste diretório vamos criar a classe Year.php
, que irá conter a nossa função:
<php
namespace DoctrineExtensions\Query\Oracle;
use Doctrine\ORM\Query\Lexer,
Doctrine\ORM\Query\AST\Functions\FunctionNode;
class Year extends FunctionNode
{
private $date;
public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
{
return sprintf(
'EXTRACT(YEAR FROM %s)',
$sqlWalker->walkArithmeticPrimary($this->date));
}
public function parse(\Doctrine\ORM\Query\Parser $parser)
{
$parser->match(Lexer::T_IDENTIFIER);
$parser->match(Lexer::T_OPEN_PARENTHESIS);
$this->date = $parser->ArithmeticPrimary();
$parser->match(Lexer::T_CLOSE_PARENTHESIS);
}
}
A classe Year
deve estender a classe FunctionNode
, que requer que sejam implementados dois métodos: getSql
e parse
. Informações mais detalhadas podem ser encontradas no artigo do cookbook do Doctrine "DQL user defined functions"
Registrando a função
Agora, só precisamos disponibilizar a função YEAR
ao DQL do Doctrine. Para isso, é necessário registrá-la, através das configurações do Doctrine no arquivo app/config/config.yml
, sob a chave dql. Logo abaixo da chave dql, você deve definir a chave do tipo da sua função, que pode ser: string_functions
, numeric_functions
ou datetime_functions
. Em seguida, vem a chave com o nome da sua função e a localização da respectiva classe:
# Doctrine Configuration
doctrine:
orm:
dql:
datetime_functions:
year: DoctrineExtensions\Query\Oracle\Year
Dica: Antes de escrever a sua função, verifique se ela já existe no repo DoctrineExtensions, que contém uma coleção de funções, com várias contribuições.