Ste*_*eve 6 php symfony doctrine-orm symfony-2.1
我有一个Doctrine2监听器和过滤器,可以过滤掉任何未经批准的/草案实体,它可以在应用它的实体上正常工作,但是,我不知道如何使它适用于它的关系.
让我们说实体被称为类别,然后我有与该类别相关的产品,当我findBy()为产品做一个时,我需要查询来检查它们所涉及的类别是否被批准.
select * from products p
left join category c on p.category_id = c.id
where p.id = 5and c.approved = true
粗体位是需要由我的过滤器或等效物注入的.
我该如何实现呢?
到目前为止,我有一个子查询作为过滤器中的一部分注入,但这似乎是地狱般的,我认为必须有一个更好的方法:
class ApprovableFilter extends SQLFilter
{
protected $listener;
protected $entityManager;
public function addFilterConstraint(ClassMetadata $targetEntity, $targetTableAlias)
{
$config = $this->getListener()->getConfiguration($this->getEntityManager(), $targetEntity->name);
/* this bit works fine for the category */
if (isset($config['approvable']) && $config['approvable']) {
$column = $targetEntity->columnNames[$config['fieldName']];
return $targetTableAlias.'.'.$column.' = true';
}
/* this bit works for products.. but seems like a pretty poor solution */
if (isset($targetEntity->associationMappings['category'])) {
$config = $this->getListener()->getConfiguration(
$this->getEntityManager(),
$targetEntity->associationMappings['category']['targetEntity']
);
return '(
select d.id from dealership d
where d.id = '.$targetTableAlias.'.dealership_id
and d.'.$config['fieldName'].' = true
) is not null';
}
}
Run Code Online (Sandbox Code Playgroud)
我能想到的最好的方法是通过类别对象检索您的产品。
这样您只需要过滤category.approved 字段。
例如:
public function addFilterConstraint(ClassMetadata $targetEntity, $targetTableAlias)
{
$config = $this->getListener()->getConfiguration($this->getEntityManager(), $targetEntity->name);
/* this bit works fine for the category */
if (isset($config['approvable']) && $config['approvable']) {
$column = $targetEntity->columnNames[$config['fieldName']];
return $targetTableAlias.'.'.$column.' = true';
}
}
Run Code Online (Sandbox Code Playgroud)
那么您的类别实体应该有一个产品集合(假设您有双向关系)。
use Doctrine\Common\Collections\ArrayCollection;
class Category {
/**
* @var ArrayCollection $products
* @ORM\OneToMany(targetEntity="Product", mappedBy="category")
*/
private $products;
public function __construct()
{
$this->products = new ArrayCollection;
}
public function getProducts()
{
return $this->products;
}
}
Run Code Online (Sandbox Code Playgroud)
这样您就可以首先检索您的类别
$category = $this->get('doctrine')->getRepository('SomeBundle:Category')->find(5);
if( $category ) {
//Here you now the category is approved
$products = $category->getProducts();
}
Run Code Online (Sandbox Code Playgroud)
希望这可以帮助。
要回答@lracicot问题并给出单向关系的示例:我将创建一个 ProjectRepository 方法,例如:
...
findByCategoryApproved( $product_id, $approved = true )
{
$query =
'SELECT p
FROM AcmeBundle:Product
LEFT JOIN p.categories c
WHERE p.id = :id AND c.approved = :approved';
return $this
->getEntityManager()
->createQuery( $query )
->setParameter( 'id', $product_id )
->setParameter( 'approved', $approved )
->getOneOrNullResult();
}
Run Code Online (Sandbox Code Playgroud)
...
$product = $doctrine
->getRepository('AcmeBundle:Product')
->findByCategoryApproved(5);
Run Code Online (Sandbox Code Playgroud)