首先,我想为这个问题的长度表示歉意;如果没有很多背景知识,我不知道如何正确地提出我的问题。请耐心等待。
我正在将一个简单的应用程序从我自己的自定义数据库访问模式转换为 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/