2014-10-07 8 views
3

Symfony를 사용하여 양식을 만들 때 양식 빌드가 매우 느리고 메모리가 급증합니다.메모리 관리 Symfony forms 및 Doctrine

양식은 일부 하위 양식을 사용하여 빌드되며 일부 one-to-many 관계를 사용합니다. 폼의 데이터가 커지면 (많은 쪽의 엔티티가 더 많아짐) 폼이 느려지고 메모리 사용량이 커지고 있습니다. 시간과 메모리 사용량이 많지는 않지만 보이게됩니다.

예 여러면에 약 71 개의 엔티티가있는 경우 메모리 사용량은 약 116MB이고로드하는 데 14 초가 걸립니다.

는 이미 메모리 스파이크는 여전히 양식

$form = $this->createForm(new TapsAndAppliancesType(), $taps);

모든 팁이 속도를하는 트릭을 작성하는 순간 발생하지만 (75 4) 수행 쿼리 수를 추론 쪽으로?

+0

으로 배열로 원하는 저장소 및 'choices'의 인스턴스로 $repository

$formBuilder->add('appliance', 'entityChoice', array( 'label' => 'My Label', 'repository' => $repository, 'choices' => $repository->getLabelsById(), 'multiple' => false, 'required' => false, 'empty_value' => '(none)', )) 

로 형태로 사용할 수 있습니다 entity' 그러나 다만'선택 'id => label'을 사용하고 [DataTransformers] (http://symfony.com/doc/current/cookbook/form/data_transformers.html)를 작성하십시오. 그런 다음 무언가를 선택했을 때 최종 값으로 만 작업합니다. – SBH

답변

4

양식에 entity 유형을 사용한다고 가정합니다. 처음 엔 모든 엔티티가 객체로 가져온 다음 약간의 id => label 스타일로 축소 되었기 때문에 매우 무겁습니다.

그래서 (그래서 아무것도 프리스트 장소에 개체로 반입하지 ​​않습니다)는 id => label -array와 함께 작동 자신의 entityChoice 유형을 작성하고이 유형에 DataTransformer를 추가 할 수 있습니다

use Symfony\Component\Form\AbstractType; 
use Symfony\Component\Form\FormBuilderInterface; 
use Symfony\Component\OptionsResolver\OptionsResolverInterface; 

use MyNamespace\EntityToIdTransformer; 

class EntityChoiceType extends AbstractType 
{ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $builder->addModelTransformer(new EntityToIdTransformer($options['repository'])); 
    } 

    public function setDefaultOptions(OptionsResolverInterface $resolver) 
    { 
     $resolver->setDefaults(array(
      'empty_value' => false, 
      'empty_data' => null, 
     )); 

     $resolver->setRequired(array(
      'repository' 
     )); 
    } 

    public function getParent() 
    { 
     return 'choice'; 
    } 

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

등 DataTransformer :

use Doctrine\ORM\EntityRepository; 
use Symfony\Component\Form\DataTransformerInterface; 
use Symfony\Component\Form\Exception\TransformationFailedException; 

class EntityToIdTransformer implements DataTransformerInterface 
{ 
    private $entityRepository; 

    public function __construct(EntityRepository $entityRepository) 
    { 
     $this->entityRepository = $entityRepository; 
    } 

    /** 
    * @param object|array $entity 
    * @return int|int[] 
    * 
    * @throws TransformationFailedException 
    */ 
    public function transform($entity) 
    { 
     if ($entity === null) { 
      return null; 
     } 
     elseif (is_array($entity) || $entity instanceof \Doctrine\ORM\PersistentCollection) { 
      $ids = array(); 
      foreach ($entity as $subEntity) { 
       $ids[] = $subEntity->getId(); 
      } 

      return $ids; 
     } 
     elseif (is_object($entity)) { 
      return $entity->getId(); 
     } 

     throw new TransformationFailedException((is_object($entity)? get_class($entity) : '').'('.gettype($entity).') is not a valid class for EntityToIdTransformer'); 
    } 

    /** 
    * @param int|array $id 
    * @return object|object[] 
    * 
    * @throws TransformationFailedException 
    */ 
    public function reverseTransform($id) 
    { 
     if ($id === null) { 
      return null; 
     } 
     elseif (is_numeric($id)) { 
      $entity = $this->entityRepository->findOneBy(array('id' => $id)); 

      if ($entity === null) { 
       throw new TransformationFailedException('A '.$this->entityRepository->getClassName().' with id #'.$id.' does not exist!'); 
      } 

      return $entity; 
     } 
     elseif (is_array($id)) { 

      if (empty($id)) { 
       return array(); 
      } 

      $entities = $this->entityRepository->findBy(array('id' => $id)); // its array('id' => array(...)), resulting in many entities!! 

      if (count($id) != count($entities)) { 
       throw new TransformationFailedException('Some '.$this->entityRepository->getClassName().' with ids #'.implode(', ', $id).' do not exist!'); 
      } 

      return $entities; 
     } 

     throw new TransformationFailedException(gettype($id).' is not a valid type for EntityToIdTransformer'); 
    } 
} 

을 그리고 마지막으로 service.yml의 새로운 유형으로 FormType을 등록

services: 
    myNamespace.form.type.entityChoice: 
     class: MyNamespace\EntityChoiceType 
     tags: 
      - { name: form.type, alias: entityChoice } 

그런 다음 '형식을 사용하지 않는 id => label

+0

나는이 [Gist] (https : //gist.github)에서이 대답을 재사용하고 개선하려고했습니다. .com/lologhi/bb900f061f8205841f6a) – LaurentG