【问题标题】:Symfony Doctrine query builder LIKE not working in PostgreSQLSymfony Doctrine 查询生成器 LIKE 在 PostgreSQL 中不起作用
【发布时间】:2017-05-06 22:56:34
【问题描述】:

所以我有一个包含以下代码的 UserRepository

namespace AppBundle\Repository;
use \Doctrine\ORM\EntityRepository;
class UserRepository extends EntityRepository
{
    public function findByRole($role)
    {
        $qb = $this->_em->createQueryBuilder();
        $qb->select('u')
            ->from($this->_entityName, 'u')
            ->where('u.roles LIKE :roles')
            ->setParameter('roles', '%"'.$role.'"%');

        return $qb->getQuery()->getResult();
    }
}

如果我的数据库是 MySQL,这似乎工作得非常好,但是如果我将数据库更改为 PostgreSQL,则此查询会引发以下错误

执行 'SELECT p0_.id AS id_0, 时发生异常, p0_.username AS username_1, p0_.password AS password_2, p0_.is_active AS is_active_3, p0_.roles AS roles_4, p0_.name AS name_5, p0_.street AS street_6, p0_.city AS city_7, p0_.state AS state_8, p0_.zip_code AS zip_code_9, p0_.phone_number AS phone_number_10, p0_.dob AS dob_11, p0_.company_name AS company_name_12, p0_.company_slug AS company_slug_13, p0_.company_logo AS company_logo_14, p0_.company_details AS company_details_15, p0_.stripe_customer_id AS stripe_customer_id_16, p0_.created_at AS created_at_17, p0_.updated_at AS updated_at_18 FROM px_user p0_ WHERE p0_.roles LIKE ?带参数 ["%\"ROLE_EMPLOYER\"%"]:

SQLSTATE[42883]:未定义函数:7 错误:运算符不存在: json ~~ 未知 LINE 1: ...at AS updated_at_18 FROM px_user p0_ WHERE p0_.roles LIKE $1 ^ 提示:没有运算符与给定名称匹配,并且 参数类型。您可能需要添加显式类型转换。

这是我第一次与PostgreSQL 合作,所以我不知道问题出在哪里。如果我通过添加以下内容将生成的查询更改为,则在玩了一段时间之后

WHERE 
  p0_.roles::text LIKE '%ROLE_EMPLOYER%'

一切正常。注意 ::text

那么现在我如何将它添加到 查询构建器 以便它也适用于 PostgreSQL。

【问题讨论】:

  • 使用->setParameter('roles', '"%'.$role.'%"');
  • @JasminMistry 我也试过了,但出现了同样的错误。
  • ->where('CAST(u.roles AS TEXT) LIKE :roles') 应该可以工作。您的 rolesjson 类型的列,因此不能直接用于代替字符串类型(引擎需要字符串类型(例如text)-LIKE 运算符(也是 ~~ ) 就是这样)。
  • @pozs 感谢分享信息,我不知道。进行更改后,我看到 [Syntax Error] line 0, col 44: Error: Expected known function, got 'CAST'
  • @Baig 然后看起来 Doctrine 解析了你给where() 的内容并且也不允许一些非常基本的 SQL。 It's not even supported in DQL。在最坏的情况下,您可以使用本机查询。

标签: php postgresql symfony doctrine-orm


【解决方案1】:

我使用模块 boldtrn/jsonb-bundle 解决了这个问题,但它根据所使用的 Postgres 版本创建了一个错误。

我还通过这样的本机查询解决了没有模块的问题:

public function findEmailsByRole($role)
{
    return $this->_em->getConnection()->executeQuery(
        "SELECT email FROM public.utilisateur WHERE roles::text LIKE :role",
        ['role'=>'%"' . $role . '"%']
    )->fetchAll();
}

【讨论】:

    【解决方案2】:

    你可以像这样创建你的函数

    PS:我也在研究 PostgreSQL

        public function findByRole($role) {
        $qb = $this->getEntityManager()->createQueryBuilder();
        $qb->select('u')
                ->from($this->getEntityName(), 'u')
                ->where("u.roles LIKE '%$role%'")
        ;
    
        return $qb->getQuery()->getResult();
    }
    

    【讨论】:

    • 您要解决什么问题?请详细说明
    • 好的,你在 ORM 中的字段类型是什么
    • 角色是数据库保存为["ROLE_USER","ROLE_EMPLOYER"]
    • 好吧,对不起,我已经遇到了这个问题,我没有找到一个好的解决方案,我可以给你一个改变的解决方案来创建一个新的字段类型文本并保存复制您的角色 Like This ROLE_USER,ROLE_EMPLOYER 并使用简单的 DQL LIKE 查找您的对象
    • 我最终修复了它,请看我的回答。我希望这可以帮助你。我很想按照您的建议添加该字段,但我不想这样做,因为必须有解决方案。
    【解决方案3】:

    我使用JsonbBundle解决了这个问题。

    按照我采取的步骤进行修复

    $ composer require "boldtrn/jsonb-bundle
    

    更新了config.yml,在其各自的位置添加了以下内容。

    doctrine:
        dbal:
            types:
              jsonb: Boldtrn\JsonbBundle\Types\JsonbArrayType
            mapping_types:
              jsonb: jsonb
        orm:
            dql:
                string_functions:
                    JSONB_AG:   Boldtrn\JsonbBundle\Query\JsonbAtGreater
                    JSONB_HGG:  Boldtrn\JsonbBundle\Query\JsonbHashGreaterGreater
                    JSONB_EX:   Boldtrn\JsonbBundle\Query\JsonbExistence
    

    roles 属性更改为类型jsonb

    在存储库中,以下查询有效

    $query = $this->getEntityManager()->createQuery("SELECT u FROM AppBundle:User u WHERE JSONB_HGG(u.roles , '{}') LIKE '%EMPLOYER%' ");
    $users = $query->getResult();
    return $users;
    

    感谢Doctrine query postgres json (contains) json_array

    【讨论】:

      【解决方案4】:
      public function findByRole($role)
      {
          $qb = $this->getEntityManager()->createQueryBuilder();
          $qb->select('u')
              ->from($this->getEntityName(), 'u')
              ->where($qb->expr()->like('u.roles', ':roles')
              ->setParameter('roles', $qb->expr()->literal('%'.$role.'%'));
      
          return $qb->getQuery()->getResult();
      }
      

      将您的自定义字符串 DQL 替换为 QueryBuilder 语法。

      我不知道它是否与您在 like 语句中得到的语法有关:'%".$var."%',这可能会出错。希望这可以帮助您解决它。

      Doctrine Querybuilder documentation like :

      // Example - $qb->expr()->like('u.firstname', $qb->expr()->literal('Gui%'))
      public function like($x, $y); // Returns Expr\Comparison instance
      

      【讨论】:

      • 感谢您查看,但这不起作用,给我同样的错误。虽然您和我编写的查询使用 MySQL 数据库,但我正在使用 PostgreSQL,但失败了。
      • 好吧太糟糕了,祝你好运寻找解决方案。如果您找到它,我希望看到(接受的)答案。
      • 我最终解决了这个问题,请看我的回答。
      • 接受您自己的答案,将问题标记为已完成。
      • 会的,它说我明天可以接受。这是我 2 天的疯狂搜索。
      【解决方案5】:

      看起来像来自PostgreSQL documentation on LIKE,您可能需要这样做:

      $qb = $this->_em->createQueryBuilder();
      $qb->select('u')
          ->from($this->_entityName, 'u')
          ->where('u.roles LIKE :roles')
          ->setParameter('roles', '\'%'.$role.'%\'');
      
      return $qb->getQuery()->getResult();
      

      通过转义它们,基本上在百分号之外加上单引号。我不确定这是否可行,但你可以试试吗?

      【讨论】:

      • 谢谢,但这也行不通。抛出同样的错误
      【解决方案6】:

      @Lou Zitoanswer为基础:

      如果您正在处理 Postgres,请了解 json/b 操作的强大功能!

      将 json/b 数组转换为文本以进行类似比较不是一个好方法。将其转换为 jsonb (甚至更好:更改您的设置/迁移以直接使用 jsonb 字段

      您可以使用? 运算符或包含运算符@> 作为示例。

      See this full list of jsonb operators available 请注意,? 将被解释为教义占位符,您需要使用 ?? 来转义它!

      public function findByRole()
      {
          return $query = $this->getEntityManager()
              ->getConnection()
              ->executeQuery(<<<'SQL'
                  SELECT id FROM public.user
                  WHERE roles::jsonb ?? :role
                  ORDER BY last_name, first_name
      SQL,
                  ['role' => User::ROLE_XYZ]
              )->fetchAllAssociative();
      }
      

      提示:正如您在上面的示例中看到的,我通常将角色提取为 User 实体中的公共字符串常量以便于访问。我也强烈建议将其作为最佳做法。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-07-21
        • 1970-01-01
        • 2017-01-13
        • 1970-01-01
        • 2011-10-02
        • 2011-12-31
        相关资源
        最近更新 更多