php - 将两个简单的 SQL 查询转换为 Doctrine

标签 php mysql doctrine-orm dql

首先,我想为这个问题的长度表示歉意;如果没有很多背景知识,我不知道如何正确地提出我的问题。请耐心等待。

我正在将一个简单的应用程序从我自己的自定义数据库访问模式转换为 Doctrine,用于磨练我的技能。我选择 Doctrine 的原因有很多,其中最重要的是我在日常工作中经常使用它。我还喜欢 Doctrine 通常是一个非常薄(看起来)的层,它在添加许多功能的同时保持不妨碍。

我已将数据库中 users 表的数据访问层转换为 Doctrine。 除了一些细节之外,它非常不起眼(只是 getter 和 setter):

  • 我需要一个用于某些特定查询的自定义存储库,并且
  • User 对象有一个在构造函数中实例化的默认 ArrayCollection
<小时/>
namespace model\entities;

/**
 * @Entity(repositoryClass="model\repositories\UserRepository")
 * @Table(name="users")
 */
class User{
    /* snip variables */

    /**
     * @OneToOne(targetEntity="Authentication", mappedBy="user", cascade="persist")
     */
    private $authentication;

    /**
     * @OneToMany(targetEntity="Contact", mappedBy="user", cascade="persist")
     */
    private $contacts;

    public function __construct() {
        $this->contacts = new \Doctrine\Common\Collections\ArrayCollection();
    }

    /* snip getters and setters */  
}
<小时/>

在我的旧架构中,我有两个自定义查询,它们选择了 users 表的子集。

他们是:

public function search( $term = null ){
    if( !$term ){
        $sql = "SELECT *
                FROM
                " . $this->tableName . "
                ORDER BY
                    lname ASC,
                    fname ASC";
        $res = $this->db->q($sql);
    }
    else{
        $sql = "SELECT *
                FROM
                " . $this->tableName . "
                WHERE
                    lname LIKE ?
                    OR fname LIKE ?
                    OR CONCAT(fname, ' ', lname) LIKE ?
                ORDER BY
                    lname ASC,
                    fname ASC";
        $values = array( '%' . $term . '%', '%' . $term . '%', '%' . $term . '%' );
        $res = $this->db->qwv( $sql, $values );
    }

    return $this->wrap( $res );
}

和:

public function getAllWithRestrictions(){
    $sql = "SELECT *
            FROM
            " . $this->tableName . "
            WHERE
                userid IN
                (
                    SELECT
                        userid
                    FROM
                        " . $this->uiPre . "authentications
                    WHERE
                        resetPassword = 1
                        OR disabled = 1
                )";
    $res = $this->db->q( $sql );

    return $this->wrap($res);
}

其中 $this->db 是一个薄 PHP PDO wrapper$this->wrap does magic返回零/单/多行并将它们转换为 data objects .

现在,我认为这很容易转换为 Doctrine。对于 getAllWithRestrictions 来说,它只是一个 ->where->orWhere 集合,对吧?我不知道了。

我发现了这些 Stackoverflow 问题,我用来尝试构建我的查询,但我遇到了一个又一个错误,而且我不确定我需要走多远:

SQL Multiple sorting and grouping
Order by multiple columns with Doctrine
Doctrine: Multiple (whereIn OR whereIn) query?
Doctrine - or where?

我的自定义存储库目前看起来像这样,但我不能说它接近正确,因为我已经摆弄它很长时间了,它只是我认为可能有效的内容的大杂烩:

<?php
namespace model\repositories;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Query\Expr;

class UserRepository extends EntityRepository{
    public function search( $term ){
        if( !$term ){
            return $this
                    ->_em
                    ->createQuery('SELECT u FROM model\entities\User u')
                    ->addOrderBy( 'u.lname' )
                    ->addOrderBy( 'u.fname' )
                    ->getResult();
        }
        else{
            $qb     = $this->_em->createQueryBuilder();

            $qb ->select(array('u'))
                ->from('model\entities\User', 'u')
                ->where( $qb->expr()->like( 'u.lname', '?1' ) )
                ->orWhere( $qb->expr()->like( 'u.fname', '?2' ) )
                ->orWhere( $qb->expr()->like( 'CONCAT(u.fname, \' \', u.lname)', '?3' ) )
                ->addOrderBy( 'u.lname' )
                ->addOrderBy( 'u.fname' )
                ->setParameters(
                    array(
                        1 => $term,
                        2 => $term,
                        3 => $term
                    )
                );

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

    public function getAllWithRestrictions(){
        $qb     = $this->_em->createQueryBuilder();

        $qb ->select(array('u'))
            ->from('model\entities\User', 'u')
            ->add('where', $qb->expr()->orx(
               $qb->expr()->eq('u.disabled', '1'),
               $qb->expr()->eq('u.resetPassword', '1')
           ));

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

编辑:我刚刚意识到我正在错误的表上执行 getAllWithRestrictions 查询(它应该是authentications。)无论如何,它都是搜索方法现在引起了我的问题。但是,我还需要知道如何执行 $qb->expr()->eq('u.Authentication.disabled = '1') 之类的操作,而且我不知道 DQL 到底如何有效。

我现在遇到的具体错误是

  • fatal error :未捕获异常“Doctrine\ORM\Query\QueryException”,消息为“SELECT u FROM model\entities\User u WHERE u.lname LIKE ?1 OR u.fname LIKE ?2 OR CONCAT(u .fname, ' ', u.lname) LIKE ?3 ORDER BY u.lname ASC, u.fname ASC'

后跟

  • Doctrine\ORM\Query\QueryException:[语法错误]第 0 行,第 99 列:错误:预期 Doctrine\ORM\Query\Lexer::T_CLOSE_PARENTHESIS,得到 ','

但是我遇到了很多不同的问题,具体取决于我构建 DQL/查询生成器的方式。

我再次希望这两个 SQL 查询能够简单地转换为 Doctrine/DQL。我想做到这一点,而不是通过 Doctrine 诉诸原始 SQL(正如我链接的许多已接受的答案所建议的那样)。这一定很容易。 有人知道如何构建优雅的 Doctrine 查询吗?

最佳答案

根据学说中的CONCAT函数解析器,它只需要2个以逗号分隔的参数,

//Doctrine/ORM/Query/AST/Functions/ConcatFunction.php
$parser->match(Lexer::T_IDENTIFIER);
$parser->match(Lexer::T_OPEN_PARENTHESIS);

$this->firstStringPrimary = $parser->StringPrimary();
$parser->match(Lexer::T_COMMA);
$this->secondStringPrimary = $parser->StringPrimary();

$parser->match(Lexer::T_CLOSE_PARENTHESIS);

所以这个

->orWhere( $qb->expr()->like( 'CONCAT(u.fname, \' \', u.lname)', '?3' ) )

应该是

->orWhere( $qb->expr()->like( 'CONCAT(u.fname, u.lname)', '?3' ) )

这不会引发任何错误,但可能不是您实际需要的。在这种情况下,您将必须为 CONCAT 推出自己的自定义函数:)

关于php - 将两个简单的 SQL 查询转换为 Doctrine,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14948804/

相关文章:

php - 检测链接何时被单击,在新框架中打开

mysql - 如何使用sql在另一个表的帮助下从两个表中获取值

mysql - 跟进查询,不包括已收集的结果

mysql - 显示语法错误,错误代码:1064 接近WITH 'cohort_items AS ( SELECT DATE_TRUNC(' MONTH', U.created_at)::date 作为队列FROM

php - java.lang.String类型的Android数据库无法转换为JSONObject

php - symfony db和学说用户结构

php - 学说 2 : inheritance mapping join with parent table

php - PHP有什么更好的方法来编写if +三元函数?

php - 为什么已经定义的环境变量需要 putenv()?

php - Zend 表单 : How do I make it bend to my will?