问题:我想在Doctrine2中使用querybuilder运行查询,如:
SELECT * FROM TABLE WHERE `column1` = 'x' and (`column2` = INET_ATON('1.1.1.1') OR `column3` like '%bla%'...)
我应该如何在Zetr2的Doctrine2中做到这一点?
我试过了:
$where->add($qb->expr()->eq('column2', $qb->expr()->literal('inet_aton('1.1.1.1'))));
但那不起作用。 Doctrine仍然在inet_aton函数周围添加引号。
答案 0 :(得分:3)
好的,我自己弄清楚了:
你应该做的一些事情:
首先制作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中具有特殊功能的人
答案 1 :(得分:2)
更新答案:(适用于新的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。
答案 2 :(得分:1)
此问题似乎与Doctrine 2 DQL MySQL equivalent to ROUND()?
重复您需要为此实现custom DQL function。
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');