INET_ATON in where statement doctrine2 query builder zend 2

时间:2013-03-25 14:40:23

标签: php mysql doctrine-orm doctrine zend-framework2

问题:我想在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函数周围添加引号。

3 个答案:

答案 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');