个性化阅读
专注于IT技术分析

如何在Symfony 4中注册自定义DQL函数(原则扩展)

本文概述

Doctrine 2的DQL解析器具有钩子来注册可以在DQL查询中使用并转换为SQL的函数, 从而允许扩展Doctrines Query功能, 而不必编写原始SQL。在本文中, 我们将向你简要介绍如何在Symfony 4项目上配置自定义原则扩展。

1.创建/选择你的DQL扩展

第一步, 在Symfony项目的src目录中创建一个目录, 即DQL。此目录将存储你要注册为自定义学说扩展的类。在此目录中, 存储在其中的文件的名称空间应为App \ DQL。在我们的例子中, 我们要注册2个自定义文本扩展名的教义(匹配和soundex), 所以我们将有2个文件, 我们的结构如下所示:

Symfony 4 DQL函数

我们将注册的MatchAgainst函数和文件MatchAgainst.php的代码如下(对你来说, 只有名称空间很重要):

namespace App\DQL;

use Doctrine\ORM\Query\Lexer;
use Doctrine\ORM\Query\AST\Functions\FunctionNode;

/**
 * "MATCH_AGAINST" "(" {StateFieldPathExpression ", "}* InParameter {Literal}? ")"
 */
class MatchAgainst extends FunctionNode {

    public $columns = array();
    public $needle;
    public $mode;

    public function parse(\Doctrine\ORM\Query\Parser $parser) {
        $parser->match(Lexer::T_IDENTIFIER);
        $parser->match(Lexer::T_OPEN_PARENTHESIS);
        do {
            $this->columns[] = $parser->StateFieldPathExpression();
            $parser->match(Lexer::T_COMMA);
        } while ($parser->getLexer()->isNextToken(Lexer::T_IDENTIFIER));
        $this->needle = $parser->InParameter();
        while ($parser->getLexer()->isNextToken(Lexer::T_STRING)) {
            $this->mode = $parser->Literal();
        }
        $parser->match(Lexer::T_CLOSE_PARENTHESIS);
    }

    public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) {
        $haystack = null;
        $first = true;
        foreach ($this->columns as $column) {
            $first ? $first = false : $haystack .= ', ';
            $haystack .= $column->dispatch($sqlWalker);
        }
        $query = "MATCH(" . $haystack .
                ") AGAINST (" . $this->needle->dispatch($sqlWalker);
        if ($this->mode) {
            $query .= " " . $this->mode->dispatch($sqlWalker) . " )";
        } else {
            $query .= " )";
        }
        
        return $query;
    }

}

拥有有效的扩展名后, 请继续进行下一步注册。

2.注册DQL扩展名

要在Symfony 4中注册DQL函数, 只需在原则中的orm的dql块下指定相应类中的类来注册它们。请记住, 在Doctrine中, DQL中只有三种类型的函数:返回数字值的函数, 返回字符串的函数和返回Date的函数, 因此必须有一个包含每种函数类型的主要块:

# config/packages/doctrine.yaml
doctrine:
    orm:
        # ...
        dql:
            string_functions:
                test_string: App\DQL\StringFunction
                second_string: App\DQL\SecondStringFunction
            numeric_functions:
                test_numeric: App\DQL\NumericFunction
            datetime_functions:
                test_datetime: App\DQL\DatetimeFunction

在我们的例子中, 使用我们的MatchAgainst和Soundex函数来处理文本, 我们只需在string_functions节点下的doctrine.yaml文件中向以下代码段注册它们即可:

# app/config/packages/doctrine.yaml
doctrine:
    # Under orm, create the DQL
    orm:
        #
        # ...
        # 
        dql:
            # Register string functions with the correct namespace
            string_functions:
                MATCH_AGAINST: App\DQL\MatchAgainst
                SOUNDEX: App\DQL\SoundexFunction

对于明确声明的实体经理

如果在Doctrine中使用多个实体管理器, 则可以在管理器块中专门为其中一些注册自定义函数:

# config/packages/doctrine.yaml
doctrine:
    orm:
        # ...
        entity_managers:
            example_manager:
                dql:
                    string_functions:
                        MATCH_AGAINST: App\DQL\MatchAgainst

编码愉快!

赞(0)
未经允许不得转载:srcmini » 如何在Symfony 4中注册自定义DQL函数(原则扩展)

评论 抢沙发

评论前必须登录!