Symfony2 - 自定义DQL函数已注册但不存在

时间:2015-11-18 02:44:50

标签: php postgresql symfony doctrine dql

我绝望地试图在Symfony2中包含LEVENSHTEIN功能,但是,我仍然收到错误。规格+到目前为止我做了什么:

  • PostgreSQL 9.3
  • 包含在fuzzystrmatch扩展中的LEVENSHTEIN
  • 通过shell执行测试了该函数。完美无缺:

    postgres=# SELECT levenshtein('test', 'text');
     levenshtein
    -------------
               1
    (1 row)
    
  • 在DQL中添加了该功能:

    <?php
    
    namespace AppBundle\DQL;
    
    use Doctrine\ORM\Query\AST\Functions\FunctionNode;
    use Doctrine\ORM\Query\Lexer;
    use Doctrine\ORM\Query\Parser;
    use Doctrine\ORM\Query\SqlWalker;
    
    class LevenshteinFunction extends FunctionNode {
    
        public $firstStringExpression = null;
    
        public $secondStringExpression = null;
    
        public function getSql(SqlWalker $sqlWalker) {
            return 'LEVENSHTEIN(' . $this->firstStringExpression->dispatch($sqlWalker) . ', ' . $this->secondStringExpression->dispatch($sqlWalker) . ')';
        }
    
        public function parse(Parser $parser) {
            // levenshtein(str1, str2)
            $parser->match(Lexer::T_IDENTIFIER);
            $parser->match(Lexer::T_OPEN_PARENTHESIS);
            $this->firstStringExpression = $parser->StringPrimary();
            $parser->match(Lexer::T_COMMA);
            $this->secondStringExpression = $parser->StringPrimary();
            $parser->match(Lexer::T_CLOSE_PARENTHESIS);
        }
    }
    

    Config.yml

    orm:
        auto_generate_proxy_classes: "%kernel.debug%"
        auto_mapping: true
        dql:
            numeric_functions:
                LEVENSHTEIN: AppBundle\DQL\LevenshteinFunction
    
  • 问题:在我的存储库中执行以下代码块时,会出现以下错误:

    $this->getEntityManager()->createQuery("SELECT LEVENSHTEIN('test', 'text') FROM AppBundle:User");
    return $query->getResult();
    
      

    SQLSTATE [42883]:未定义的函数:7错误:函数levenshtein(未知,未知)不存在

我错过了什么?为什么DQL / Symfony / PDO / ...没有识别这个功能?任何帮助都非常感谢!

2 个答案:

答案 0 :(得分:1)

您的函数类对我来说似乎没问题,但您的配置可能有误。这就是我对CAST函数所拥有的:

doctrine:
    orm:
        dql:
            string_functions:
                CAST: App\MyBundle\Doctrine\DBAL\Functions\Porgres\Cast

您应该注意,您对不同类型的函数有不同的集合,例如string_functionsnumeric_functionsdatetime_functions。所有这些都列在官方documentation中。

除此之外,清理缓存后,您的代码应该正常工作。

答案 1 :(得分:1)

错误来自Postgres,似乎是一个可见性问题。

当然,必须安装附加模块fuzzystrmatch。你显然这样做了,或者你的函数调用在psql中也不起作用。

如果它在psql中有效,但在你的应用中却没有,那么只剩下几个可能的解释。显而易见的第一个:

  • 是否已连接到同一个数据库? (相同的服务器,相同的端口,相同的数据库?)

  • 您正在与同一位用户联系?可能 ......

  • 如果与其他用户连接(但无论如何),请检查您是否使用相同的搜索路径。在任一连接中运行并进行比较:

    SHOW search_path;
    

    详细信息 - 以及如何设置search_path

请注意,扩展程序可以安装到您选择的任何架构中。默认是search_path中的第一个架构(安装时的“当前架构”,通常为public,但我不知道您的安装。文档:

  

如果未指定,则扩展名的控制文件未指定   schema,或者使用当前的默认对象创建模式。

运行此命令以诊断一些事情:

SELECT e.extname AS extension, nsp.nspname AS schema
     , r.rolname AS schema_owner, nsp.nspacl AS schema_acl
FROM   pg_extension e
JOIN   pg_namespace nsp ON nsp.oid = e.extnamespace
JOIN   pg_roles     r   ON r.oid = nsp.nspowner

你会得到类似的东西:

   extension   |   schema   | schema_owner |             schema_acl

---------------+------------+--------------+-------------------------------------
 adminpack     | pg_catalog | postgres     | {postgres=UC/postgres,=U/postgres}
 plpgsql       | pg_catalog | postgres     | {postgres=UC/postgres,=U/postgres}
 fuzzystrmatch | public     | postgres     | {postgres=UC/postgres,=UC/postgres}
 tablefunc     | public     | postgres     | {postgres=UC/postgres,=UC/postgres}
 ...

如果schema_acl包含=U/postgresU for USAGE),则public角色可以访问,即每个人。

相应地设置连接的search_path或(重新)安装到可见的模式,它应该可以工作。

理论上,拥有角色或超级用户可能已撤消函数本身的EXECUTE权限...