Symfony3 - 在视图中显示一对多关系

时间:2017-10-16 07:20:24

标签: symfony doctrine-orm

拥有这些表,实体(伪代码以显示关系)。

article 

id
name
author_id
type_id
category_id

author

id 
name

type

id
name

category

id 
name

现在在我的控制器中,我这样做

  public function indexAction()
    {
        $articles = $this->getDoctrine()
                ->getRepository('AppBundle:Articles')
                ->findAll();
        $authors = $this->getDoctrine()
                ->getRepository('AppBundle:Author');
        $types = $this->getDoctrine()
                ->getRepository('AppBundle:Type');
        $categories = $this->getDoctrine()
                ->getRepository('AppBundle:Category');

        return $this->render('article/index.html.twig', array(
            'articles' => $articles,
            'authors' => $authors,
            'types' => $types,
            'categories' => $categories
        ));
    }

在我看来,这个:

<tbody> 
            {% for exploit in exploits %}
            <tr> 
                <th scope="row">{{ article.id }}</th> 
                <td>{{ article.name }}</td> 

                <td> {{ authors.findOneById(article.author) }} </td>
                <td> {{ types.findOneById(article.type) }} </td>
                <td> {{ categories.findOneById(article.category) }} </td>

                <td>{{ article.date|date('F j, Y, g:i a') }}</td> 
                <td>
                    <a href="/details/{{ article.id }}" class="btn btn-success">View</a>
                    <a href="/edit/{{ article.id }}" class="btn btn-default">Edit</a>
                    <a href="/delete/{{ article.id }}" class="btn btn-danger">Delete</a>
                </td> 
            </tr> 
            {% endfor %}
        </tbody> 

这样可行,但它会对每个条目执行查询,这不是最佳选择。

如何在Controller和View中更容易地显示它?没有这么多的查询,只有一个。

谢谢,

更新3:

按照Salah的建议,但仍然是同样的错误:

Impossible to access an attribute ("name") on a integer variable ("1").

我现在使用Exploit Entity。而不是Article Entity。

::::::::::::::
Author.php
::::::::::::::
<?php
namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use AppBundle\Entity\Exploit;

/**
 * Author
 *
 * @ORM\Table(name="author", indexes={@ORM\Index(name="author_name_id_idx", columns={"id"})})
 * @ORM\Entity
 */
class Author
{

    /**
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="NONE")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="name", author="string", length=255, nullable=false)
     */
    private $name;


/**
 * @ORM\OneToMany(targetEntity="AppBundle\Entity\Exploit", mappedBy="author", cascade={"persist", "remove"})
 * @ORM\JoinColumn(name="exploits", referencedColumnName="id")
 */
private $exploits;

/**
 * Author constructor.
 */
public function __construct()
{
    $this->exploits = new ArrayCollection();
}

    /**
     * Set name
     *
     * @param string $name
     *
     * @return Author
     */
    public function setName($name)
    {
        $this->name = $name;

        return $this;
    }

    /**
     * Get name
     *
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Get id
     *
     */
    public function getId()
    {
        return $this->id;
    }

    public function __toString() 
    {
        return $this->name;
    }


/**
 * @param Exploits $exploit
 *
 * @return Author
 */
public function addExploit($exploit)
{
        $this->exploits->add($exploit);

    return $this;
}

/**
 * @param Collection $exploits
 *
 * @return Author
 */
public function setExploits(Collection $exploits)
{
    $this->exploits->clear();

    foreach ($exploits as $exploit) {
        $exploit->add($this);
    }

    $this->exploits = $exploits;

    return $this;
}
}
::::::::::::::
Category.php
::::::::::::::
<?php
namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use AppBundle\Entity\Exploit;

/**
 * Category
 *
 * @ORM\Table(name="category", indexes={@ORM\Index(name="category_name_id_idx", columns={"id"})})
 * @ORM\Entity
 */
class Category
{

    /**
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="NONE")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="name", category="string", length=255, nullable=false)
     */
    private $name;


/**
 * @ORM\OneToMany(targetEntity="AppBundle\Entity\Exploit", mappedBy="category", cascade={"persist", "remove"})
 * @ORM\JoinColumn(name="exploits", referencedColumnName="id")
 */
private $exploits;

/**
 * Author constructor.
 */
public function __construct()
{
    $this->exploits = new ArrayCollection();
}

    /**
     * Set name
     *
     * @param string $name
     *
     * @return Author
     */
    public function setName($name)
    {
        $this->name = $name;

        return $this;
    }

    /**
     * Get name
     *
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Get id
     *
     */
    public function getId()
    {
        return $this->id;
    }

    public function __toString() 
    {
        return $this->name;
    }


/**
 * @param Exploits $exploit
 *
 * @return Author
 */
public function addExploit($exploit)
{
        $this->exploits->add($exploit);

    return $this;
}

/**
 * @param Collection $exploits
 *
 * @return Author
 */
public function setExploits(Collection $exploits)
{
    $this->exploits->clear();

    foreach ($exploits as $exploit) {
        $exploit->add($this);
    }

    $this->exploits = $exploits;

    return $this;
}
}
::::::::::::::
Exploit.php
::::::::::::::
<?php

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use AppBundle\Entity\Author;
use AppBundle\Entity\Type;
use AppBundle\Entity\Category;

/**
 * Exploit
 *
 * @ORM\Table(name="exploit", indexes={@ORM\Index(name=exploit_category_idx", columns={"category"}), @ORM\Index(name="exploit_type_idx", columns={"type"}), @ORM\Index(name="exploit_author_idx", columns={"
author"})})
 * @ORM\Entity
 */
class Exploit
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="bigint", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="edb_id", type="string", length=100, nullable=false)
     */
    private $edbId;

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="date", type="datetime", nullable=false)
     */
    private $date;

     /**
     * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Author", inversedBy="exploits")
     * @ORM\JoinColumn(name="author", referencedColumnName="id")
     */
    private $author;

    /**
     * @var string
     *
     * @ORM\Column(name="name", type="string", length=255, nullable=false)
     */
    private $name;

     /**
     * @var integer
     *
     * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Category", inversedBy="exploits")
     * @ORM\JoinColumn(name="category", referencedColumnName="id")
     */
    private $category;

    /**
     * @var string
     *
     * @ORM\Column(name="version", type="string", length=255, nullable=false)
     */
    private $version;

     /**
     * @var integer
     *
     * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Type", inversedBy="exploits")
     * @ORM\JoinColumn(name="type", referencedColumnName="id")
     */
    private $type;

    /**
     * @var string
     *
     * @ORM\Column(name="content", type="text", nullable=false)
     */
    private $content;

    /**
     * @var string
     *
     * @ORM\Column(name="dork", type="string", length=255, nullable=true)
     */
    private $dork;

    /**
     * @var string
     *
     * @ORM\Column(name="software_link", type="string", length=255, nullable=true)
     */
    private $softwareLink;

    /**
     * @var string
     *
     * @ORM\Column(name="tested_on", type="string", length=255, nullable=true)
     */
    private $testedOn;



    /**
     * Set edbId
     *
     * @param integer $edbId
     *
     * @return Exploit
     */
    public function setEdbId($edbId)
    {
        $this->edbId = $edbId;

        return $this;
    }

    /**
     * Get edbId
     *
     * @return integer
     */
    public function getEdbId()
    {
        return $this->edbId;
    }

    /**
     * Set date
     *
     * @param \DateTime $date
     *
     * @return Exploit
     */
    public function setDate($date)
    {
        $this->date = $date;

        return $this;
    }

    /**
     * Get date
     *
     * @return \DateTime
     */
    public function getDate()
    {
        return $this->date;
    }

    /**
     * Set author
     *
     * @param integer $author
     *
     * @return Exploit
     */
    public function setAuthor($author)
    {
        $this->author = $author;

        return $this;
    }

    /**
     * Get author
     *
     * @return integer
     */
    public function getAuthor()
    {
        return $this->author;
    }

    /**
     * Set name
     *
     * @param string $name
     *
     * @return Exploit
     */
    public function setName($name)
    {
        $this->name = $name;

        return $this;
    }

    /**
     * Get name
     *
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Set category
     *
     * @param integer $category
     *
     * @return Exploit
     */
    public function setCategory($category)
    {
        $this->category = $category;

        return $this;
    }

    /**
     * Get category
     *
     * @return integer
     */
    public function getCategory()
    {
        return $this->category;
    }

    /**
     * Set version
     *
     * @param string $version
     *
     * @return Exploit
     */
    public function setVersion($version)
    {
        $this->version = $version;

        return $this;
    }

    /**
     * Get version
     *
     * @return string
     */
    public function getVersion()
    {
        return $this->version;
    }

    /**
     * Set type
     *
     * @param integer $type
     *
     * @return Exploit
     */
    public function setType($type)
    {
        $this->type = $type;

        return $this;
    }

    /**
     * Get type
     *
     * @return integer
     */
    public function getType()
    {
        return $this->type;
    }

    /**
     * Set content
     *
     * @param string $content
     *
     * @return Exploit
     */
    public function setContent($content)
    {
        $this->content = $content;

        return $this;
    }

    /**
     * Get content
     *
     * @return string
     */
    public function getContent()
    {
        return $this->content;
    }

    /**
     * Set dork
     *
     * @param string $dork
     *
     * @return Exploit
     */
    public function setDork($dork)
    {
        $this->dork = $dork;

        return $this;
    }

    /**
     * Get dork
     *
     * @return string
     */
    public function getDork()
    {
        return $this->dork;
    }

    /**
     * Set softwareLink
     *
     * @param string $softwareLink
     *
     * @return Exploit
     */
    public function setSoftwareLink($softwareLink)
    {
        $this->softwareLink = $softwareLink;

        return $this;
    }

    /**
     * Get softwareLink
     *
     * @return string
     */
    public function getSoftwareLink()
    {
        return $this->softwareLink;
    }

    /**
     * Set testedOn
     *
     * @param string $testedOn
     *
     * @return Exploit
     */
    public function setTestedOn($testedOn)
    {
        $this->testedOn = $testedOn;

        return $this;
    }

    /**
     * Get testedOn
     *
     * @return string
     */
    public function getTestedOn()
    {
        return $this->testedOn;
    }

    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }
}
::::::::::::::
Type.php
::::::::::::::
<?php
namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use AppBundle\Entity\Exploit;

/**
 * Type
 *
 * @ORM\Table(name="type", indexes={@ORM\Index(name="type_name_id_idx", columns={"id"})})
 * @ORM\Entity
 */
class Type
{

    /**
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="NONE")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="name", type="string", length=255, nullable=false)
     */
    private $name;


/**
 * @ORM\OneToMany(targetEntity="AppBundle\Entity\Exploit", mappedBy="type", cascade={"persist", "remove"})
 * @ORM\JoinColumn(name="exploits", referencedColumnName="id")
 */
private $exploits;

/**
 * Type constructor.
 */
public function __construct()
{
    $this->exploits = new ArrayCollection();
}

    /**
     * Set name
     *
     * @param string $name
     *
     * @return Type
     */
    public function setName($name)
    {
        $this->name = $name;

        return $this;
    }

    /**
     * Get name
     *
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Get id
     *
     */
    public function getId()
    {
        return $this->id;
    }

    public function __toString() 
    {
        return $this->name;
    }


/**
 * @param Exploits $exploit
 *
 * @return Type
 */
public function addExploit($exploit)
{
        $this->exploits->add($exploit);

    return $this;
}

/**
 * @param Collection $exploits
 *
 * @return Type
 */
public function setExploits(Collection $exploits)
{
    $this->exploits->clear();

    foreach ($exploits as $exploit) {
        $exploit->add($this);
    }

    $this->exploits = $exploits;

    return $this;
}
}

3 个答案:

答案 0 :(得分:1)

indexAction()中,您只需编写:

$articles = $this->getDoctrine()
            ->getRepository('AppBundle:Articles')
            ->findAll();

视图

<th scope="row"> {{ article.id }} </th> 
        <td> {{ article.name }} </td> 
        <td> {{ article.author_id.name }} </td>
        <td> {{ article.type_id.name }} </td>
        <td> {{ article.category_id.name }} </td>
        <td>{{ article.date|date('F j, Y, g:i a') }}</td>  

P.S:而不是author_id,type_id,category_id,你可以命名它们:author,type, 没有&#39; _id&#39;

的类别

修改

<强> Article.php

<?php

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use AppBundle\Entity\Author;
use AppBundle\Entity\Type;
use AppBundle\Entity\Category;

/**
 * Article
 *
 * @ORM\Table(name="Article", indexes={@ORM\Index(name="Article_category_idx", columns={"category"}), @ORM\Index(name="Article_type_idx", columns={"type"}), @ORM\Index(name="Article_author_idx", columns={"author"})})
 * @ORM\Entity
 */
class Article
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="bigint", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="edb_id", type="string", length=100, nullable=false)
     */
    private $edbId;

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="date", type="datetime", nullable=false)
     */
    private $date;

     /**
     * @var Author
     *
     * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Author", inversedBy="articles")
     * @ORM\JoinColumn(name="author", referencedColumnName="id")
     */
    private $author;

    /**
     * @var string
     *
     * @ORM\Column(name="name", type="string", length=255, nullable=false)
     */
    private $name;

    /**
     * @var integer
     *
     * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Category", inversedBy="articles")
     * @ORM\JoinColumn(name="category", referencedColumnName="id")
     */
    private $category;

    /**
     * @var string
     *
     * @ORM\Column(name="version", type="string", length=255, nullable=false)
     */
    private $version;

    /**
     * @var integer
     *
     * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Type", inversedBy="articles")
     * @ORM\JoinColumn(name="type", referencedColumnName="id")
     */
    private $type;

    /**
     * @var string
     *
     * @ORM\Column(name="content", type="text", nullable=false)
     */
    private $content;

    /**
     * @var string
     *
     * @ORM\Column(name="dork", type="string", length=255, nullable=true)
     */
    private $dork;

    /**
     * @var string
     *
     * @ORM\Column(name="software_link", type="string", length=255, nullable=true)
     */
    private $softwareLink;

    /**
     * @var string
     *
     * @ORM\Column(name="tested_on", type="string", length=255, nullable=true)
     */
    private $testedOn;



    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set edbId
     *
     * @param string $edbId
     *
     * @return Article
     */
    public function setEdbId($edbId)
    {
        $this->edbId = $edbId;

        return $this;
    }

    /**
     * Get edbId
     *
     * @return string
     */
    public function getEdbId()
    {
        return $this->edbId;
    }

    /**
     * Set date
     *
     * @param \DateTime $date
     *
     * @return Article
     */
    public function setDate($date)
    {
        $this->date = $date;

        return $this;
    }

    /**
     * Get date
     *
     * @return \DateTime
     */
    public function getDate()
    {
        return $this->date;
    }

    /**
     * Set author
     *
     * @param Author $author
     *
     * @return Article
     */
    public function setAuthor($author)
    {
        $this->author = $author;

        return $this;
    }

    /**
     * Get author
     *
     * @return Author
     */
    public function getAuthor()
    {
        return $this->author;
    }

    /**
     * Set name
     *
     * @param string $name
     *
     * @return Article
     */
    public function setName($name)
    {
        $this->name = $name;

        return $this;
    }

    /**
     * Get name
     *
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Set category
     *
     * @param Category $category
     *
     * @return Article
     */
    public function setCategory($category)
    {
        $this->category = $category;

        return $this;
    }

    /**
     * Get category
     *
     * @return Category
     */
    public function getCategory()
    {
        return $this->category;
    }

    /**
     * Set version
     *
     * @param string $version
     *
     * @return Article
     */
    public function setVersion($version)
    {
        $this->version = $version;

        return $this;
    }

    /**
     * Get version
     *
     * @return string
     */
    public function getVersion()
    {
        return $this->version;
    }

    /**
     * Set type
     *
     * @param Type $type
     *
     * @return Article
     */
    public function setType($type)
    {
        $this->type = $type;

        return $this;
    }

    /**
     * Get type
     *
     * @return Type
     */
    public function getType()
    {
        return $this->type;
    }

    /**
     * Set content
     *
     * @param string $content
     *
     * @return Article
     */
    public function setContent($content)
    {
        $this->content = $content;

        return $this;
    }

    /**
     * Get content
     *
     * @return string
     */
    public function getContent()
    {
        return $this->content;
    }

    /**
     * Set dork
     *
     * @param string $dork
     *
     * @return Article
     */
    public function setDork($dork)
    {
        $this->dork = $dork;

        return $this;
    }

    /**
     * Get dork
     *
     * @return string
     */
    public function getDork()
    {
        return $this->dork;
    }

    /**
     * Set softwareLink
     *
     * @param string $softwareLink
     *
     * @return Article
     */
    public function setSoftwareLink($softwareLink)
    {
        $this->softwareLink = $softwareLink;

        return $this;
    }

    /**
     * Get softwareLink
     *
     * @return string
     */
    public function getSoftwareLink()
    {
        return $this->softwareLink;
    }

    /**
     * Set testedOn
     *
     * @param string $testedOn
     *
     * @return Article
     */
    public function setTestedOn($testedOn)
    {
        $this->testedOn = $testedOn;

        return $this;
    }

    /**
     * Get testedOn
     *
     * @return string
     */
    public function getTestedOn()
    {
        return $this->testedOn;
    }
}

<强> Type.php:

<?php
namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use AppBundle\Entity\Author;

/**
 * Type
 *
 * @ORM\Table(name="type", indexes={@ORM\Index(name="type_name_id_idx", columns={"id"})})
 * @ORM\Entity
 */
class Type
{

    /**
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="NONE")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="name", type="string", length=255, nullable=false)
     */
    private $name;


/**
 * @ORM\OneToMany(targetEntity="AppBundle\Entity\Article", mappedBy="type", cascade={"persist", "remove"})
 * @ORM\JoinColumn(name="articles", referencedColumnName="id")
 */
private $articles;

/**
 * Type constructor.
 */
public function __construct()
{
    $this->articles = new ArrayCollection();
}

    /**
     * Set name
     *
     * @param string $name
     *
     * @return Type
     */
    public function setName($name)
    {
        $this->name = $name;

        return $this;
    }

    /**
     * Get name
     *
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Get id
     *
     */
    public function getId()
    {
        return $this->id;
    }

    public function __toString() 
    {
        return $this->name;
    }


/**
 * @param Articles $article
 *
 * @return Type
 */
public function addArticle($article)
{
        $this->articles->add($article);

    return $this;
}

/**
 * @param Collection $articles
 *
 * @return Type
 */
public function setArticles(Collection $articles)
{
    $this->articles->clear();

    foreach ($articles as $article) {
        $article->add($this);
    }

    $this->articles = $articles;

    return $this;
}
}

然后你做类别和作者的类型

答案 1 :(得分:1)

在您的实体以及漏洞利用

<强>之前

<body onresize="sizer()">

将其更改为

/**
 * @ORM\OneToMany(targetEntity="AppBundle\Entity\Exploit",mappedBy="author", cascade={"persist", "remove"})
 * @ORM\JoinColumn(name="exploits", referencedColumnName="id")
 */
private $exploits;

这是因为实体漏洞利用是所有关系的拥有方。运行/** * @ORM\OneToMany(targetEntity="AppBundle\Entity\Exploit",mappedBy="author", cascade={"persist", "remove"}) */ private $exploits; 以更新数据库结构。

在漏洞利用实体中

bin/console doctrine:schema:update --force

在您的控制器中

/**
 * Exploit
 *
 * @ORM\Table(name="exploit", indexes={@ORM\Index(name=exploit_category_idx", columns={"category"}), @ORM\Index(name="exploit_type_idx", columns={"type"}), @ORM\Index(name="exploit_author_idx", columns={"
author"})})
 * @ORM\Entity(repositoryClass="AppBundle\Repository\ExploitRepository")
 */
class Exploit
{
// class properties and methods as is
}

在您的存储库类

 public function indexAction()
    {
        $exploits = $this->getDoctrine()
                ->getRepository('AppBundle:Exploit')
                ->fetchAllExploits();

        return $this->render('article/index.html.twig', array(
            'exploits' => $exploits
        ));
    }

在您的视图中

class ExploitRepository extends EntityRepository
{
    public function fetchAllExploits(){
        return $this
        ->createQueryBuilder('e')
        ->leftJoin('e.author','a')
        ->addSelect('a')
        ->leftJoin('e.type','t')
        ->addSelect('t')
        ->leftJoin('e.category','c')
        ->addSelect('c')
        ->getQuery()
        ->getResult();

    }
}

答案 2 :(得分:0)

创建自定义查询加入关系和addSelect(连接的别名)。

Doctrine关系处于Lazy fetch模式,这就是为什么它只在你得到它时加载关系。如果您进行自定义查询并选择关系原则,只需使用一个查询即可对其进行水合。