Have these tables, entities (pseudo Code to show the relations).
article
id
name
author_id
type_id
category_id
author
id
name
type
id
name
category
id
name
Now in my controller, I do this
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
));
}
and in my View, this:
<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>
This works, but it executes query for each entry, which is not optimal.
How do I display it in Controller and View easier? Without making so many queries, but just one.
Thanks,
Update 3:
Did as suggested by Salah, but still the same error:
Impossible to access an attribute ("name") on a integer variable ("1").
Instead of Article Entity, I use now Exploit 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;
}
}
Create a custom Query With Join into your relations and addSelect(alias of your join).
Doctrine relation are in Lazy fetch mode, that's why it load relation only when you get it. If you make your custom query and you select relation doctrine hydrate them with only one query.
In your indexAction(), you just have to write:
And in your view:
P.S: Instead of author_id, type_id, category_id, you can name them: author, type, category without the '_id'
EDIT:
Article.php
Type.php:
And then you do the same as Type for Category and Author
In your Entities other than Exploit
Before
Change them to
This is because entity Exploit is the owning side of all relations. Run
bin/console doctrine:schema:update --force
to update database structure.In Exploit Entity
In your controller
In your repository class
In your view