通过从Doctrine的收藏中获得特定物品的正确方法



我在自己的项目中第一次使用教义。我面临着从教义一对多关系返回的集合中找到正确对象的问题。

假设我有一个实体Page它有很多Section子实体。

/**
* @ORMEntity
* @ORMTable(name="Pages")
*/
class Page 
{
// bunch of properties
/**
* @ORMOneToMany(targetEntity="Section", mappedBy="page")
* @var Collection 
*/ 
protected $sections;
public function __construct() 
{
$this->sections = new ArrayCollection();
}
/**
* @return Collection
*/
public function getSections(): Collection
{
return $this->sections;
}
}

现在我想要实现的是能够通过名称获取Section(我可能应该提到nameSection实体的属性)。

所以最后我希望能够实现类似于:

class SomeController 
{
public function HomePageAction() 
{
$page = $this->getEntityManager()
->getRepository('App:Entity:Page')
->findOneBy(array('name' => 'homepage'));
$section = $page->findSectionByName('header');
// rendering etc.
}
}

当然,我可以遍历所有部分并返回与我正在寻找的名称匹配的部分(如果没有,则抛出异常),或者我想知道是否有更简单的方法可以做到这一点?另外,我应该在某种自定义存储库类中执行某些操作,还是可以将方法findSectionByName保留在Entity类中?提前谢谢你。

所以,到目前为止我尝试过...

// class AppEntityPage
public function getSectionByName(string $name)
{
foreach ($this->getSections() as $section) {
if ($section->getName() === $name) 
return $section;
}
return null;
}

最佳做法是对集合使用匹配(条件$criteria)函数。

所以:

use DoctrineCommonCollectionsCriteria;
public function getSectionByName(string $name)
{
$criteria = Criteria::create()
->where(Criteria::expr()->eq('name', $name))
->setFirstResult(0)
->setMaxResults(1);
return $this->getSections()->matching($criteria)->first();
}

如果要引发未找到异常,最佳做法是在操作中执行此操作:

public function HomePageAction() 
{
$page = $this->getEntityManager()
->getRepository('App:Entity:Page')
->findOneBy(array('name' => 'homepage'));
$section = $page->findSectionByName('header');
if($section === false) {
//here throw your exception.
}
// rendering etc.
}

有关过滤教义馆藏的更多信息,请参阅教义 - 与协会合作

您还可以在Page实体中生成自定义存储库

/**
* @ORMEntity(repositoryClass="AppRepositoryPageRepository")
*/
class Page
{
....
}

之后,在您的AppRepositoryPageRepository定义函数,该函数将按页面和部分名称获取部分

// AppRepositoryPageRepository
public function getSectionByPageAndName($pageName, $sectionName)
{
return $this->getEntityManager()
->createQueryBuilder()
->select('s')
->from(Page::class, 'p')
->join(Section::class, 's')
->where('p.name = :pageName')
->andWhere('s.name = :sectionName')
->setParameter('pageName', $pageName)
->setParameter('sectionName', $sectionName)
->getQuery()
->getResult();
}

之后,您可以轻松使用此功能 一遍又一遍,只是在你的控制器中调用存储库上的函数

class SomeController
{
public function HomePageAction()
{
$sections = $this->getEntityManager()
->getRepository('App:Entity:Page')
->getSectionByPageAndName($pageName, $sectionName);
//etc
}
}

因为你的关系是@OneToMany的,如果sectionName不是唯一的$sections将是空数组或Section对象的数组,如果您只想限制为一个结果或其他内容,请检查文档

相关内容

  • 没有找到相关文章

最新更新