'Symfony doctrine specify fields in ManyToOne to improve performance?
For example i have a simple entity "Cars" with a ManyToOne relation "Brands".
class Brands
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", nullable=false)
*/
private $name;
/**
* @ORM\Column(type="string", nullable=false)
*/
private $country;
}
public function getCountry(): ?string
{
return $this->country;
}
Cars entity :
class Cars
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", nullable=false)
*/
private $name;
/**
* @ORM\ManyToOne(targetEntity="App\Entity\Brands")
*/
private $brand;
}
public function getBrand(): ?Brands
{
return $this->brand;
}
public function getBrandCountry(): ?string
{
return $this->getBrand()->getCountry();
}
If on my template i do {{ car.getBrandCountry}} (or {{ car.brand.name}} on template), the request executed on database will do :
SELECT t0.id, t0.name, t0.field3, t0.field4, t0.field5 [..........] FROM brands t0 WHERE t0.id = ?
But i only need "name" or "country" field from Brands, not others. On my list i have 500 lines to display and Symfony did 500 SELECT * only for load 2 fields that is very bad for performances.
How i can do to obtain something like that (to get only fields i need, not all fields.) :
SELECT name, country FROM brands WHERE id = 'xx'
Thanks for your help
Solution 1:[1]
There are three solutions to your problem :
You build a first query which will collect the content of the
brandstable.
With doctrine cache, when you will query thecars, doctrine won't query thebrandstable again as it have it in it's cache.You query your
carstable, collect the brand ids from the result and then query yourbrandstable with the ids you collected. In this case, you will not do something likecars.brands.namein twig (else doctrine gonna make extra query). I would suggest to rebuildbrandsarray result to make an associative one ([brand_id]=>[brand_data])Make a partial query : https://www.doctrine-project.org/projects/doctrine-orm/en/2.11/reference/partial-objects.html
Solution 2:[2]
The best practices is to add a new function in Repository of your Entity, and use it after in your controller for ex in your case:
public function getCustomDataById($brandId)
{
return $this->createQueryBuilder('b')
->select('b.name, b.country')
->where('b.id', $brandId)
->getQuery()
->getResult();
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Preciel |
| Solution 2 | Muhamed RAFYQ |
