Reputation: 2458
Example I have a Entity User which have a Contact. How I get the Contact ID without joining the contact table.
$user = $entityManager->userRepository->findUserById(1);
$contactId = $user->getContact()->getId();
when `getContact() is called the whole contact is loaded from the DB. How I can avoid this SQL request without add a join in findUserById. I only need to contactId which is in my users table, but there is no simple function like $user->getContactId().
Upvotes: 1
Views: 1609
Reputation: 946
Your situation sounds perfect for the Doctrine Second Level Cache
With this, the first query will be gotten from DB but every subsequent query will be from the second level cache, plus if you change the data using doctrine then the cache is automatically updated. For this reason, I suggest you set a very long time for the cache my personal favourite is 1 month approx 2592000 seconds.
Enable it in your user entity like so
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use FOS\UserBundle\Model\User as BaseUser;
use Doctrine\Common\Collections\ArrayCollection;
/**
* @ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository")
* @ORM\Cache(usage="NONSTRICT_READ_WRITE", region="users_region")
* @ORM\Table(
* name="site_users",
* indexes={
* @ORM\Index(name="username_index", columns={"username"}),
* @ORM\Index(name="email_index", columns={"email"}),
* @ORM\Index(name="enabled_index", columns={"enabled"}),
* @ORM\Index(name="last_login_index", columns={"last_login"})
* }
*)
*/
class User extends BaseUser
{
/**
* @ORM\Id
* @ORM\Column(name="id", type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
......
Then in your config.yml like so
orm:
auto_generate_proxy_classes: "%kernel.debug%"
entity_managers:
default:
connection: default
auto_mapping: true
naming_strategy: doctrine.orm.naming_strategy.underscore
second_level_cache:
enabled: true
# region_lock_lifetime: 60
region_lifetime: 300
log_enabled: %kernel.debug%
region_cache_driver: apc
regions:
users_region:
region_lifetime: 2592000
region_cache_driver: apc
............
More information here
http://symfony.com/doc/master/bundles/DoctrineBundle/configuration.html
Note this method also ensure that the popular check for an authenticated user $user = $this->getUser();
does not hit your DB as well.
Upvotes: 1
Reputation: 2106
Look at this post Getting only ID from entity relations without fetching whole object in Doctrine. I tested a simple example in a ManyToOne relation and the related object was not loaded.
Upvotes: 1
Reputation: 39430
I suggest you to change fetch mode in the specific query, as described here in the doc.
So you can describe your query as follow:
// Supposing this method in the repository class
public function findUserById($idUser)
{
$qb = $this->createQueryBuilder('u')
->where("u.id = :idUser")
->setParameter("idUser", $idUser);
$query = $qb->getQuery();
// Describe here all the entity and the association name that you want to fetch eager
$query->setFetchMode("YourBundle\\Entity\\Contract", "contract", ClassMetadata::FETCH_EAGER);
...
return $qb->->getResult();
}
NB:
Changing the fetch mode during a query is only possible for one-to-one and many-to-one relations.
Hope this help
Upvotes: 0