3

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

4

3 回答 3

4

好的,我自己想通了:

你应该做的几件事:

先做一个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 中具有特殊功能的人

于 2013-03-26T06:10:19.820 回答
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 文档中的解释

于 2016-01-12T22:42:39.270 回答
1

这个问题似乎是等同于 ROUND() 的 Doctrine 2 DQL MySQL 的副本?

您需要为此实现自定义 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');
于 2013-03-26T06:09:22.037 回答