假设我有一个与Account
实体有关联的实体Profile
。我想获取profileCode = 12345
和的配置文件,其中相关的Account
具有my@email.com
的电子邮件地址。因此,我需要在两个实体上指定一个条件。
为此,我创建了一个自定义存储库Repository'Profile
,现在我想知道如何实现这一点。我知道我可以使用"原始"DQL查询或使用查询生成器来解决所有这些问题。然而,我觉得它不像我想的那么漂亮,因为它非常接近原始SQL。当然语法有点不同,但从概念上讲,我更倾向于考虑SQL而不是OOP。我会经常做这些事情,所以我真的在努力用最好的方式来做。
我对Criteria
对象做了一些阅读(文档很少),只要我对单个实体进行过滤,它看起来真的很棒。在过滤关联实体时,我无法找到使用Criteria
的任何解决方案。
所以基本上我的问题是:是否有任何方法可以使用Criteria
对象直接从数据库中过滤多个实体,并在自定义存储库中?我真的更喜欢在自定义存储库中编码,而不是像我看到的一些人那样在实体本身中编码。这是可能的吗?或者有什么好的替代方案吗?或者纯DQL或查询构建器真的是可行的吗?
标准只能过滤实体本身的关联,但如果我理解你的用例,你需要过滤2层深度,所以它不会工作。
你想要按照"你的方式"做事,试图把教义塑造成不符合教义的东西。从长远来看,这只会伤害到你。解决方案已经有了,使用DQL是非常好的,特别是在存储库中。
我不明白为什么不,虽然不确定你的关联是如何相关的。One-to-One
、One-to-Many
、Many-to-Many
如果你试图从第3关联深度级别检索记录,如Account.profile
->Profile.code
→Code.xxx (not id)
您将需要使用DQL或QueryBuilder来建立什么概要文件和代码加入帐户或解析代码实体提供给标准。
假设One-to-Many
,其中一个帐户有多个配置文件。您也可以选择在实体本身中定义它,以使其更容易管理并减少对getProfiles()
的额外调用。
存储库使用
use Doctrine'ORM'EntityRepository;
use Doctrine'Common'Collections'Criteria;
class AccountRepository extends EntityRepository {
/**
* @var string|Account $accountOrEmail
* @var string $code
* @return Profile|null
*/
public function getAccountProfileByEmailAndCode($accountOrEmail, $code)
{
try{
$account = ($accountOrEmail instanceof Account ? $accountOrEmail: $this->findOneBy(['email' => $accountOrEmail]));
if (!$account instanceof Account) {
throw new 'InvalidArgumentException('Unknown Account Specified.');
}
$criteria = Criteria::create()->setMaxResult(1);
$expr = $criteria::expr();
$criteria->where($expr->eq('code', $code));
return $account->getProfiles()->matching($criteria)->first() ?: null;
} catch('Exception $e) {
return null;
}
}
}
$accountRepo = $em->getRepository(''Entities'Account');
$profile = $accountRepo->getAccountProfileByEmailAndCode('my@email.com', '12345');
实体使用
use Doctrine'Common'Collections'Criteria;
/**
* @ORM'Entity(repositoryClass="AccountRepository")
*/
class Account {
// ...
public function getProfiles(Criteria $criteria = null)
{
if ($criteria instanceof Criteria) {
return $this->profiles->matching($criteria);
}
return $this->profiles;
}
/**
* @var string $code
* @return null|Profile
*/
public function getProfileByCode($code)
{
$criteria = Criteria::create()->setMaxResult(1);
$expr = $criteria::expr();
$criteria->where($expr->eq('code', $code));
return $this->getProfiles($criteria)->first() ?: null;
}
}
$account = $em->getRepository(''Entities'Account')->findOneBy(['email' => 'my@email.com']);
$profile = $account->getProfileByCode('12345');