我在自己的项目中第一次使用教义。我面临着从教义一对多关系返回的集合中找到正确对象的问题。
假设我有一个实体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
(我可能应该提到name
是Section
实体的属性)。
所以最后我希望能够实现类似于:
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
对象的数组,如果您只想限制为一个结果或其他内容,请检查文档