树枝模板中的 ManyToOne
ManyToOne in a twig template
我有以下表格(以及 symfony2 / doctrine2 中的实体):
+------------------+ +--------------------+
| forum_sections | | forum_categories |
+------------------+ +--------------------+
| id ├--------| | id |
| title | |---------| section |
| position | | position |
| created_at | | title |
+------------------+ | description |
+--------------------+
我想存档以下 html 页面(不带项目符号):
- 这是一个标题(来自forum_sections->title)
- 论坛 1(来自 forum_categories->标题)
- 论坛 2(来自 forum_categories->标题)
- 这是另一个标题(来自forum_sections->title)
- 论坛 3(来自 forum_categories->标题)
我研究了如何做到这一点。到目前为止,我在我的树枝布局中尝试了以下内容:
{% for section in sections %}
<h1>title</h1>
{% for category in categories %}
bla bla
{% endfor %}
{% endfor %}
在 Doctrine2 中使用 'findAll' 查询甚至可能吗?我尝试了一些组合,但它们似乎让所有的板都忽略了这些部分。
Twig 不会更改循环内的上下文(与其他一些模板语言不同)。作用域与原生 PHP.
基本相同
如果你有一个 Section
实体(或关联数组)并且它有很多 Category
entities/arrays 那么你将在将 array('sections' => $sections)
传递给 Twig 之后执行此操作渲染函数。
{% for section in sections %}
<h1>{{ section.title }}</h1>
<ul>
{% for category in section.categories %}
<li>{{ category.title }}</li>
{% endfor %}
</ul>
{% endfor %}
我认为问题在于您的实体,即您定义实体之间关系的方式。您需要使用双向映射 http://doctrine-orm.readthedocs.org/en/latest/reference/association-mapping.html#one-to-many-bidirectional
我更新了您的实体以满足您的需要。
- 已将类别添加到
ForumSection
个实体
- 向
ForumSection
实体添加了 addCategory()、removeCategory()、getCategories() 方法
- 向
ForumCategory
实体添加了 inversedBy
注释以完成关系
- 我使用 getCategories() 方法获取了 twig 中该部分的所有类别。
实体;
ForumSection.php
namespace AppBundle\Entity;
/**
* @version 0.0.1
* @copyright (c) 2015 Ricardo Jacobs. All rights reserved.
* @license Proprietary and confidential source code.
*/
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* @ORM\Entity(repositoryClass="AppBundle\Entity\Repositories\Forum")
* @ORM\HasLifecycleCallbacks
* @ORM\Table(name="forum_sections")
*/
class ForumSection
{
/**
* @ORM\Column(type="integer", name="id")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @ORM\Column(type="string", length=255, name="title")
*/
private $title;
/**
* @ORM\Column(type="integer", name="position")
*/
private $position;
/**
* @ORM\Column(type="datetime")
*/
private $created_at;
/**
* @ORM\OneToMany(targetEntity="AppBundle\Entity\ForumCategory", mappedBy="section")
*/
private $categories;
public function __construct() {
$this->categories = new ArrayCollection();
}
public function getCategories() {
return $this->categories;
}
/**
* Add category
*
* @param AppBundle\Entity\ForumCategory
* @return ForumSection
*/
public function addCategory(\AppBundle\Entity\ForumCategory $category)
{
$this->categories[] = $category;
return $this;
}
/**
* Remove category
*
* @param AppBundle\Entity\ForumCategory $category
*/
public function removeCategory(\AppBundle\Entity\ForumCategory $category)
{
$this->categories->removeElement($category);
}
/**
* @ORM\PrePersist
* @ORM\PreUpdate
*/
public function updatedTimestamps() {
if ($this->getCreatedAt() == null) {
$this->setCreatedAt(new \DateTime('NOW'));
}
}
/**
* @return mixed
*/
public function getId() {
return $this->id;
}
/**
* @return mixed
*/
public function getTitle() {
return $this->title;
}
/**
* @param $title
* @return $this
*/
public function setTitle($title) {
$this->title = $title;
return $this;
}
/**
* @return mixed
*/
public function getPosition() {
return $this->position;
}
/**
* @param $position
* @return $this
*/
public function setPosition($position) {
$this->position = $position;
return $this;
}
/**
* @return Date
*/
public function getCreatedAt() {
return $this->created_at;
}
/**
* @param $date
*/
public function setCreatedAt($date) {
$this->created_at = $date;
return $this;
}
}
ForumCategory.php
<?php
namespace AppBundle\Entity;
/**
* @version 0.0.1
* @copyright (c) 2015 Ricardo Jacobs. All rights reserved.
* @license Proprietary and confidential source code.
*/
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass="AppBundle\Entity\Repositories\Forum")
* @ORM\Table(name="forum_categories")
*/
class ForumCategory
{
/**
* @ORM\Column(type="integer", name="id")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\ForumSection", inversedBy="categories")
* @ORM\JoinColumn(name="section", referencedColumnName="id")
*/
private $section;
/**
* @ORM\Column(type="integer", name="position")
*/
private $position;
/**
* @ORM\Column(type="string", length=255, name="title")
*/
private $title;
/**
* @ORM\Column(type="string", length=255, nullable=true, name="description")
*/
private $description;
/**
* @return mixed
*/
public function getId() {
return $this->id;
}
/**
* @return mixed
*/
public function getSection() {
return $this->section;
}
/**
* @param $section
* @return $this
*/
public function setSection($section) {
$this->section = $section;
return $this;
}
/**
* @return mixed
*/
public function getPosition() {
return $this->position;
}
/**
* @param $position
* @return $this
*/
public function setPosition($position) {
$this->position = $position;
return $this;
}
/**
* @return mixed
*/
public function getTitle() {
return $this->title;
}
/**
* @param $title
* @return $this
*/
public function setTitle($title) {
$this->title = $title;
return $this;
}
/**
* @return mixed
*/
public function getDescription() {
return $this->description;
}
/**
* @param $description
* @return $this
*/
public function setDescription($description) {
$this->description = $description;
return $this;
}
}
控制器;
public function indexAction()
{
$em = $this->get('doctrine')->getManager();
$sections = $sections = $this->getDoctrine() ->getRepository('AppBundle:ForumSection') ->findAll();
return $this->render('AppBundle:Default:index.html.twig', array('sections'=>$sections));
}
模板;
<ol>
{% for forum in sections %}
<li>
<h2>{{forum.title}} </h2>
<ul>
{% for category in forum.getCategories() %}
<li>{{category.title}}</li>
{% endfor %}
</ul>
</li>
{% endfor %}
</ol>
现在您可以访问与数据库中每个 forum_section 行相关的类别。
这是我运行代码
后的输出
-
你好
- 你好第1节
- 你好第2节
-
世界
- 世界第 1 部分
- 世界第 2 部分
我不得不提一下,Doctrine 使用延迟加载 default.Doctrine 将执行额外的查询来查找与论坛相关的类别。如果您有 n
个论坛,您将有 n + 1
个查询。在我的例子中,我使用了 2 个论坛部分,这里是查询。
这个找到所有 forum_section;
SELECT
t0.id AS id1,
t0.title AS title2,
t0.position AS position3,
t0.created_at AS created_at4
FROM
forum_sections t0
然后对于每个论坛,doctrine 执行另一个查询以查找具有不同参数的类别。
在您调用“forum.getCategories()”方法之前,不会执行此查询。
SELECT
t0.id AS id1,
t0.position AS position2,
t0.title AS title3,
t0.description AS description4,
t0.section AS section5
FROM
forum_categories t0
WHERE
t0.section = ? [Parameters: 1,2]
查看 fetch-join 概念以了解有关延迟加载和替代方案的更多信息。
http://blog.bemycto.com/good-practices/2015-05-31/understanding-doctrine-orm-lazy-load-fetch-join/
我有以下表格(以及 symfony2 / doctrine2 中的实体):
+------------------+ +--------------------+
| forum_sections | | forum_categories |
+------------------+ +--------------------+
| id ├--------| | id |
| title | |---------| section |
| position | | position |
| created_at | | title |
+------------------+ | description |
+--------------------+
我想存档以下 html 页面(不带项目符号):
- 这是一个标题(来自forum_sections->title)
- 论坛 1(来自 forum_categories->标题)
- 论坛 2(来自 forum_categories->标题)
- 这是另一个标题(来自forum_sections->title)
- 论坛 3(来自 forum_categories->标题)
我研究了如何做到这一点。到目前为止,我在我的树枝布局中尝试了以下内容:
{% for section in sections %}
<h1>title</h1>
{% for category in categories %}
bla bla
{% endfor %}
{% endfor %}
在 Doctrine2 中使用 'findAll' 查询甚至可能吗?我尝试了一些组合,但它们似乎让所有的板都忽略了这些部分。
Twig 不会更改循环内的上下文(与其他一些模板语言不同)。作用域与原生 PHP.
基本相同如果你有一个 Section
实体(或关联数组)并且它有很多 Category
entities/arrays 那么你将在将 array('sections' => $sections)
传递给 Twig 之后执行此操作渲染函数。
{% for section in sections %}
<h1>{{ section.title }}</h1>
<ul>
{% for category in section.categories %}
<li>{{ category.title }}</li>
{% endfor %}
</ul>
{% endfor %}
我认为问题在于您的实体,即您定义实体之间关系的方式。您需要使用双向映射 http://doctrine-orm.readthedocs.org/en/latest/reference/association-mapping.html#one-to-many-bidirectional
我更新了您的实体以满足您的需要。
- 已将类别添加到
ForumSection
个实体 - 向
ForumSection
实体添加了 addCategory()、removeCategory()、getCategories() 方法 - 向
ForumCategory
实体添加了inversedBy
注释以完成关系 - 我使用 getCategories() 方法获取了 twig 中该部分的所有类别。
实体;
ForumSection.php
namespace AppBundle\Entity;
/**
* @version 0.0.1
* @copyright (c) 2015 Ricardo Jacobs. All rights reserved.
* @license Proprietary and confidential source code.
*/
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* @ORM\Entity(repositoryClass="AppBundle\Entity\Repositories\Forum")
* @ORM\HasLifecycleCallbacks
* @ORM\Table(name="forum_sections")
*/
class ForumSection
{
/**
* @ORM\Column(type="integer", name="id")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @ORM\Column(type="string", length=255, name="title")
*/
private $title;
/**
* @ORM\Column(type="integer", name="position")
*/
private $position;
/**
* @ORM\Column(type="datetime")
*/
private $created_at;
/**
* @ORM\OneToMany(targetEntity="AppBundle\Entity\ForumCategory", mappedBy="section")
*/
private $categories;
public function __construct() {
$this->categories = new ArrayCollection();
}
public function getCategories() {
return $this->categories;
}
/**
* Add category
*
* @param AppBundle\Entity\ForumCategory
* @return ForumSection
*/
public function addCategory(\AppBundle\Entity\ForumCategory $category)
{
$this->categories[] = $category;
return $this;
}
/**
* Remove category
*
* @param AppBundle\Entity\ForumCategory $category
*/
public function removeCategory(\AppBundle\Entity\ForumCategory $category)
{
$this->categories->removeElement($category);
}
/**
* @ORM\PrePersist
* @ORM\PreUpdate
*/
public function updatedTimestamps() {
if ($this->getCreatedAt() == null) {
$this->setCreatedAt(new \DateTime('NOW'));
}
}
/**
* @return mixed
*/
public function getId() {
return $this->id;
}
/**
* @return mixed
*/
public function getTitle() {
return $this->title;
}
/**
* @param $title
* @return $this
*/
public function setTitle($title) {
$this->title = $title;
return $this;
}
/**
* @return mixed
*/
public function getPosition() {
return $this->position;
}
/**
* @param $position
* @return $this
*/
public function setPosition($position) {
$this->position = $position;
return $this;
}
/**
* @return Date
*/
public function getCreatedAt() {
return $this->created_at;
}
/**
* @param $date
*/
public function setCreatedAt($date) {
$this->created_at = $date;
return $this;
}
}
ForumCategory.php
<?php
namespace AppBundle\Entity;
/**
* @version 0.0.1
* @copyright (c) 2015 Ricardo Jacobs. All rights reserved.
* @license Proprietary and confidential source code.
*/
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass="AppBundle\Entity\Repositories\Forum")
* @ORM\Table(name="forum_categories")
*/
class ForumCategory
{
/**
* @ORM\Column(type="integer", name="id")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\ForumSection", inversedBy="categories")
* @ORM\JoinColumn(name="section", referencedColumnName="id")
*/
private $section;
/**
* @ORM\Column(type="integer", name="position")
*/
private $position;
/**
* @ORM\Column(type="string", length=255, name="title")
*/
private $title;
/**
* @ORM\Column(type="string", length=255, nullable=true, name="description")
*/
private $description;
/**
* @return mixed
*/
public function getId() {
return $this->id;
}
/**
* @return mixed
*/
public function getSection() {
return $this->section;
}
/**
* @param $section
* @return $this
*/
public function setSection($section) {
$this->section = $section;
return $this;
}
/**
* @return mixed
*/
public function getPosition() {
return $this->position;
}
/**
* @param $position
* @return $this
*/
public function setPosition($position) {
$this->position = $position;
return $this;
}
/**
* @return mixed
*/
public function getTitle() {
return $this->title;
}
/**
* @param $title
* @return $this
*/
public function setTitle($title) {
$this->title = $title;
return $this;
}
/**
* @return mixed
*/
public function getDescription() {
return $this->description;
}
/**
* @param $description
* @return $this
*/
public function setDescription($description) {
$this->description = $description;
return $this;
}
}
控制器;
public function indexAction()
{
$em = $this->get('doctrine')->getManager();
$sections = $sections = $this->getDoctrine() ->getRepository('AppBundle:ForumSection') ->findAll();
return $this->render('AppBundle:Default:index.html.twig', array('sections'=>$sections));
}
模板;
<ol>
{% for forum in sections %}
<li>
<h2>{{forum.title}} </h2>
<ul>
{% for category in forum.getCategories() %}
<li>{{category.title}}</li>
{% endfor %}
</ul>
</li>
{% endfor %}
</ol>
现在您可以访问与数据库中每个 forum_section 行相关的类别。
这是我运行代码
后的输出
-
你好
- 你好第1节
- 你好第2节
-
世界
- 世界第 1 部分
- 世界第 2 部分
我不得不提一下,Doctrine 使用延迟加载 default.Doctrine 将执行额外的查询来查找与论坛相关的类别。如果您有 n
个论坛,您将有 n + 1
个查询。在我的例子中,我使用了 2 个论坛部分,这里是查询。
这个找到所有 forum_section;
SELECT
t0.id AS id1,
t0.title AS title2,
t0.position AS position3,
t0.created_at AS created_at4
FROM
forum_sections t0
然后对于每个论坛,doctrine 执行另一个查询以查找具有不同参数的类别。 在您调用“forum.getCategories()”方法之前,不会执行此查询。
SELECT
t0.id AS id1,
t0.position AS position2,
t0.title AS title3,
t0.description AS description4,
t0.section AS section5
FROM
forum_categories t0
WHERE
t0.section = ? [Parameters: 1,2]
查看 fetch-join 概念以了解有关延迟加载和替代方案的更多信息。
http://blog.bemycto.com/good-practices/2015-05-31/understanding-doctrine-orm-lazy-load-fetch-join/