问题:我想在 Doctrine2 中使用 querybuilder 运行查询,例如:
SELECT * FROM TABLE WHERE `column1` = 'x' and (`column2` = INET_ATON('1.1.1.1') OR `column3` like '%bla%'...)
我应该如何使用 Zend2 在 Doctrine2 中执行此操作?
我试过这个:
$where->add($qb->expr()->eq('column2', $qb->expr()->literal('inet_aton('1.1.1.1'))));
但这行不通。 Doctrine 仍然在 inet_aton 函数周围添加引号。
好吧,我自己想出来了:
您应该做的几件事:
首先制作一个DQL函数
<?php
namespace Application\DQL;
use Doctrine\ORM\Query\Lexer;
class InetAtonFunction extends \Doctrine\ORM\Query\AST\Functions\FunctionNode
{
public $valueExpression = null;
/**
* parse
*
* @param \Doctrine\ORM\Query\Parser $parser
* @access public
* @return void
*/
public function parse(\Doctrine\ORM\Query\Parser $parser)
{
$parser->match(Lexer::T_IDENTIFIER);
$parser->match(Lexer::T_OPEN_PARENTHESIS);
$this->valueExpression = $parser->StringPrimary();
$parser->match(Lexer::T_CLOSE_PARENTHESIS);
}
/**
* getSql
*
* @param \Doctrine\ORM\Query\SqlWalker $sqlWalker
* @access public
* @return string
*/
public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
{
return 'INET_ATON('. $this->valueExpression->dispatch($sqlWalker) . ')';
}
}
之后将函数添加到 Doctrine ORM 中
<?php
namespace Observer;
//...
class Module implements
AutoloaderProviderInterface,
ConfigProviderInterface,
ServiceProviderInterface
{
//...
public function onBootstrap($e)
{
$application = $e->getParam('application');
$sm = $application->getServiceManager();
$em = $application->getEventManager();
$entityManager = $sm->get('doctrine.entitymanager.orm_default');
$entityManager->getConfiguration()->addCustomStringFunction('inet_aton', 'Application\DQL\InetAtonFunction');
}
...
此后你就可以出发了。 现在您可以使用 querybuilder 运行查询,如
SELECT whatever FROM someting where cloumn = inet_aton(:?)
我希望这可以帮助其他在 Doctrine 和 Zend Framework2 中具有特殊功能的人
只是更新的答案:(对于新的 SF 版本)
创建 DQL 函数后(请参阅较早的帖子),
我们想在 Yaml (config.yml) 中注册自定义 DQL 类,如下所示:
doctrine:
dbal:
driver: "%database_driver%"
host: "%database_host%"
port: "%database_port%"
dbname: "%database_name%"
user: "%database_user%"
password: "%database_password%"
orm:
auto_generate_proxy_classes: "%kernel.debug%"
auto_mapping: true
dql:
string_functions:
inet_aton: home\myBundle\myFolderContaintClass\InetAton
这是 Symfony 官方文档中here的解释。
这个问题似乎是Doctrine 2 DQL MySQL相当于ROUND()的重复?
您需要为此实现一个 自定义 DQL 函数。
DoctrineExtensions中有一些例子。
您可以像下面这样实现:
<?php
namespace MyApp\DQL;
use Doctrine\ORM\Query\AST\Functions\FunctionNode;
use Doctrine\ORM\Query\Lexer;
use Doctrine\ORM\Query\SqlWalker;
class InetAnon extends FunctionNode
{
private $arithmeticExpression;
public function getSql(SqlWalker $sqlWalker)
{
return 'INET_ANON(' . $sqlWalker->walkSimpleArithmeticExpression(
$this->arithmeticExpression
) . ')';
}
public function parse(\Doctrine\ORM\Query\Parser $parser)
{
$lexer = $parser->getLexer();
$parser->match(Lexer::T_IDENTIFIER);
$parser->match(Lexer::T_OPEN_PARENTHESIS);
$this->arithmeticExpression = $parser->SimpleArithmeticExpression();
$parser->match(Lexer::T_CLOSE_PARENTHESIS);
}
}
然后您可以在引导 ORM 时将其注册到配置中:
$config = new \Doctrine\ORM\Configuration();
$config->addCustomNumericFunction('INET_ANON', 'MyApp\DQL\InetAnon');
自
Doctrine ORM v2.19.0
起,升级指南中进行了更改
弃用 Doctrine\ORM\Query\Lexer::T_* 常量
使用 Doctrine\ORM\Query\TokenType::T_* 代替。
更新了代码示例
<?php
namespace App\DQL;
use Doctrine\ORM\Query\AST\Functions\FunctionNode;
use Doctrine\ORM\Query\AST\SimpleArithmeticExpression;
use Doctrine\ORM\Query\TokenType;
use Doctrine\ORM\Query\SqlWalker;
use Doctrine\ORM\Query\Parser;
use Doctrine\ORM\Query\QueryException;
class InetAton extends FunctionNode
{
private SimpleArithmeticExpression $arithmeticExpression;
/**
* @param SqlWalker $sqlWalker
* @return string
*/
public function getSql(SqlWalker $sqlWalker): string
{
return 'INET_ATON(' . $sqlWalker->walkSimpleArithmeticExpression(
$this->arithmeticExpression
) . ')';
}
/**
* @param Parser $parser
* @return void
* @throws QueryException
*/
public function parse(Parser $parser): void
{
$parser->match(TokenType::T_IDENTIFIER);
$parser->match(TokenType::T_OPEN_PARENTHESIS);
$this->arithmeticExpression = $parser->SimpleArithmeticExpression();
$parser->match(TokenType::T_CLOSE_PARENTHESIS);
}
}