Query Cache Per Request

New topics about Symfony 2 should go here

Moderators: dcobalt, tiagojsag

Query Cache Per Request

Postby trsteel88 » Wed Jun 06, 2012 6:04 am

How can I make Symfony cache the queries per request. I have a form which is using the entity field type.
This is a One2Many entity in the form so it appears more than once. However, it queries the database for each row. Shouldn't it only do this once?

Code: Select all
        $builder
            ->add('preset_parent', 'entity', array(
                'property'      => 'title',
                'class'         => 'Vivo\JobsystemBundle\Entity\Component',
                'empty_value'   => '',
                'query_builder' => function(EntityRepository $er) {
                    return $er->createQueryBuilder('c')
                        ->where('c.status = :status')
                        ->setParameter('status', Component::STATUS_PRESET)
                        ->orderBy('c.title', 'asc')
                    ;
                },
                'attr' => array(
                    'class' => 'preset_parent',
                )
            ))


+ SELECT v0_.id AS id0, v0_.status AS status1, v0_.title AS title2, v0_.description AS description3, v0_.price AS price4, v0_.created_at AS created_at5, v0_.updated_at AS updated_at6, v0_.parent_id AS parent_id7, v0_.project_id AS project_id8 FROM vivo_jobsystem_component v0_ WHERE v0_.status = ? ORDER BY v0_.title ASC
Parameters: [0]
Time: 13.62 ms
+ SELECT v0_.id AS id0, v0_.status AS status1, v0_.title AS title2, v0_.description AS description3, v0_.price AS price4, v0_.created_at AS created_at5, v0_.updated_at AS updated_at6, v0_.parent_id AS parent_id7, v0_.project_id AS project_id8 FROM vivo_jobsystem_component v0_ WHERE v0_.status = ? ORDER BY v0_.title ASC
Parameters: [0]
Time: 0.46 ms
+ SELECT v0_.id AS id0, v0_.status AS status1, v0_.title AS title2, v0_.description AS description3, v0_.price AS price4, v0_.created_at AS created_at5, v0_.updated_at AS updated_at6, v0_.parent_id AS parent_id7, v0_.project_id AS project_id8 FROM vivo_jobsystem_component v0_ WHERE v0_.status = ? ORDER BY v0_.title ASC
Parameters: [0]
Time: 22.80 ms
+ SELECT v0_.id AS id0, v0_.status AS status1, v0_.title AS title2, v0_.description AS description3, v0_.price AS price4, v0_.created_at AS created_at5, v0_.updated_at AS updated_at6, v0_.parent_id AS parent_id7, v0_.project_id AS project_id8 FROM vivo_jobsystem_component v0_ WHERE v0_.status = ? ORDER BY v0_.title ASC
Parameters: [0]
Time: 0.51 ms
trsteel88
Member
 
Posts: 64
Joined: Tue Jun 21, 2011 11:18 am

Re: Query Cache Per Request

Postby loudo » Tue Jun 12, 2012 7:33 pm

Here is my solution.
I create a service which make the query and keep result in a array.
Code: Select all
<?php
namespace Soc\AbsenceBundle\manager;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\EntityManager;
use Soc\IntranetBundle\Manager\BaseManager;
use Soc\AbsenceBundle\Entity\TypeAbsence;

class TypeAbsenceManager extends BaseManager
{
   
   protected $em;
   protected $typeAbsenceCacheTab;
   
   public function __construct($em)
   {
      $this->em = $em;

      // Mise en cache des types d'absence
      $typeAbsences = $this->getRepository()->findAll();

      foreach ($typeAbsences as $typeAbsence) {
         $this->typeAbsenceCacheTab[$typeAbsence->getCode()] = $typeAbsence;
      }

   }
   
   /**
    * Repository
    */
   public function getRepository()
   {
      return $this->em->getRepository('SocAbsenceBundle:TypeAbsence');
   }

   /**
    * getter typeAbsenceCacheTab
    */
   public function getTypeAbsenceCacheTab()
   {
      return $this->typeAbsenceCacheTab;
   }
}


I create a dataTransformer for my choicetype. It transform a choice in the list into an entity.

Code: Select all
<?php

namespace Soc\AbsenceBundle\Form\DataTransformer;

use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;
use Doctrine\Common\Persistence\ObjectManager;
use Soc\IntranetBundle\Entity\Collaborateur;

class TypeAbsenceToCodeTransformer implements DataTransformerInterface
{
    /**
     * @var array
     */
    private $data;

    /**
     * @param ObjectManager $om
     */
    public function __construct($data)
    {
        $this->data = $data;

    }

    /**
     * Transforms an object (TypeAbsence) to a string (code).
     *
     * @param  TypeAbsence|null $typeAbsence
     * @return string
     */
    public function transform($typeAbsence)
    {
        if (null === $typeAbsence or $typeAbsence == "") {
            return "";
        }

        return $typeAbsence->getCode();
    }

    /**
     * Transforms a string (code) to an object (TypeAbsence).
     *
     * @param  string $code
     * @return TypeAbsence|null
     * @throws TransformationFailedException if object (TypeAbsence) is not found.
     */
    public function reverseTransform($code)
    {
       

        if (!$code) {
            return null;
        }

        if (array_key_exists($code, $this->data))
            $typeAbsence = $this->data[$code];
        else
            throw new TransformationFailedException(sprintf(
                'Le code TypeAbsence "%s" n\'existe pas!',
                $code
            ));

        return $typeAbsence;
    }
}


Create a new selector type which use the transformer.

Code: Select all
<?php

namespace Soc\AbsenceBundle\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilder;
use Soc\AbsenceBundle\Form\DataTransformer\TypeAbsenceToCodeTransformer;
use Doctrine\Common\Persistence\ObjectManager;

class TypeAbsenceSelectorType extends AbstractType
{

    private $tabTypeAbsence;

    private $choices;

    /**
     * @param $manager
     */
    public function __construct($manager)
    {
        $this->tabTypeAbsence = $manager->getTypeAbsenceCacheTab();

        foreach ($this->tabTypeAbsence as $key => $value) {
            $this->choices[$key] = $value->getLibelle();   
        }

    }

    public function buildForm(FormBuilder $builder, array $options)
    {
        $builder->resetClientTransformers();
        $transformer = new TypeAbsenceToCodeTransformer($this->tabTypeAbsence);
        $builder->appendClientTransformer($transformer);
    }

    public function getDefaultOptions(array $options)
    {
        return array(
            'invalid_message' => 'password.err.code_inconnu',
            'choices'         => $this->choices
        );
    }

    public function getParent(array $options)
    {
        return 'choice';
    }

    public function getName()
    {
        return 'typeabsence_selector';
    }
}


Define your service

Code: Select all
 
form.type.typeabsence_selector:
        class: Soc\AbsenceBundle\Form\Type\TypeAbsenceSelectorType
        arguments: ["@soc_absence.typeabsence"]
        tags:
            - { name: form.type, alias: typeabsence_selector }


Then use your type in your form.

Code: Select all
<?php
namespace Soc\AbsenceBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilder;
use Soc\AbsenceBundle\Entity\DetailAbsence;

class DetailAbsenceType extends AbstractType {
   
   public function buildForm(FormBuilder $builder, array $options)
   {
      
      $builder->add('dateAbsence', 'madate')
                /*->add('typeAbsence', 'entity', array(
                             'class' => 'SocAbsenceBundle:TypeAbsence'))*/
            ->add('typeAbsence', 'typeabsence_selector')
            ->add('typeJournee', 'entity', array(
                             'class' => 'SocAbsenceBundle:TypeJournee'))
             ->add('commentaire', 'text', array('read_only'=> false));
   }
   
   public function getName()
   {
      return 'detailabsence';
   }
   
   public function getDefaultOptions(array $options)
   {
      return $options + array('data_class' => 'Soc\AbsenceBundle\Entity\DetailAbsence');
   }

}


Insted using entity use typeabsence_selector
loudo
Junior Member
 
Posts: 23
Joined: Wed Oct 19, 2011 11:47 am


Return to General Symfony 2 discussion

Who is online

Users browsing this forum: Google [Bot] and 7 guests