2015-03-14 4 views
0

У меня есть сложная форма со множеством полей выбора объектов. Когда я не использую проверку, добавьте/отредактируйте в порядке. Но когда я включаю проверку формы в /config/validation.yml, я больше не могу добавлять/редактировать. Я проверил файлы журналов PHP и увидеть некоторые ошибки:Symfony2 форма проверки исчерпана память

PHP Fatal error: Allowed memory size of 536870912 bytes exhausted (tried to allocate 32 bytes) in ..\example.com\vendor\doctrine\dbal\lib\Doctrine\DBAL\Connection.php on line 694 
PHP Stack trace: 
PHP 1. {main}() ..\example.com\web\app_dev.php:0 
PHP 2. Symfony\Component\HttpKernel\Kernel->handle() ..\example.com\web\app_dev.php:29 
PHP 3. Symfony\Component\HttpKernel\DependencyInjection\ContainerAwareHttpKernel->handle() ..\example.com\var\bootstrap.php.cache:2377 
PHP 4. Symfony\Component\HttpKernel\HttpKernel->handle() ..\example.com\var\bootstrap.php.cache:3133 
PHP 5. Symfony\Component\HttpKernel\HttpKernel->handleRaw() ..\example.com\var\bootstrap.php.cache:2984 
PHP 6. call_user_func_array:{..\example.com\var\bootstrap.php.cache:3022}() ..\example.com\var\bootstrap.php.cache:3022 
PHP 7. DefaultBundle\Controller\PropertyHouseController->createAction() ..\example.com\var\bootstrap.php.cache:3022 
PHP 8. Symfony\Component\Form\Form->createView() ..\example.com\src\DefaultBundle\Controller\PropertyHouseController.php:86 
PHP 9. Symfony\Component\Form\Form->createView() ..\example.com\vendor\symfony\symfony\src\Symfony\Component\Form\Form.php:1061 
PHP 10. Symfony\Component\Form\Extension\DataCollector\Proxy\ResolvedTypeDataCollectorProxy->buildView() ..\example.com\vendor\symfony\symfony\src\Symfony\Component\Form\Form.php:1058 
PHP 11. Symfony\Component\Form\ResolvedFormType->buildView() ..\example.com\vendor\symfony\symfony\src\Symfony\Component\Form\Extension\DataCollector\Proxy\ResolvedTypeDataCollectorProxy.php:111 
PHP 12. Symfony\Component\Form\Extension\DataCollector\Proxy\ResolvedTypeDataCollectorProxy->buildView() ..\example.com\vendor\symfony\symfony\src\Symfony\Component\Form\ResolvedFormType.php:159 
PHP 13. Symfony\Component\Form\ResolvedFormType->buildView() ..\example.com\vendor\symfony\symfony\src\Symfony\Component\Form\Extension\DataCollector\Proxy\ResolvedTypeDataCollectorProxy.php:111 
PHP 14. Symfony\Component\Form\Extension\Core\Type\ChoiceType->buildView() ..\example.com\vendor\symfony\symfony\src\Symfony\Component\Form\ResolvedFormType.php:162 
PHP 15. Symfony\Bridge\Doctrine\Form\ChoiceList\EntityChoiceList->getPreferredViews() ..\example.com\vendor\symfony\symfony\src\Symfony\Component\Form\Extension\Core\Type\ChoiceType.php:101 
PHP 16. Symfony\Bridge\Doctrine\Form\ChoiceList\EntityChoiceList->load() ..\example.com\vendor\symfony\symfony\src\Symfony\Bridge\Doctrine\Form\ChoiceList\EntityChoiceList.php:174 
PHP 17. Symfony\Bridge\Doctrine\Form\ChoiceList\ORMQueryBuilderLoader->getEntities() ..\example.com\vendor\symfony\symfony\src\Symfony\Bridge\Doctrine\Form\ChoiceList\EntityChoiceList.php:430 
PHP 18. Doctrine\ORM\AbstractQuery->execute() ..\example.com\vendor\symfony\symfony\src\Symfony\Bridge\Doctrine\Form\ChoiceList\ORMQueryBuilderLoader.php:71 
PHP 19. Doctrine\ORM\Query->_doExecute() ..\example.com\vendor\doctrine\orm\lib\Doctrine\ORM\AbstractQuery.php:794 
PHP 20. Doctrine\ORM\Query\Exec\SingleSelectExecutor->execute() ..\example.com\vendor\doctrine\orm\lib\Doctrine\ORM\Query.php:286 
PHP 21. Doctrine\DBAL\Connection->executeQuery() ..\example.com\vendor\doctrine\orm\lib\Doctrine\ORM\Query\Exec\SingleSelectExecutor.php:50 
PHP 22. PDOStatement->execute() ..\example.com\vendor\doctrine\dbal\lib\Doctrine\DBAL\Connection.php:694 

Как исправить эту ошибку? Спасибо за помощь.

У меня сложная форма

public function buildForm(FormBuilderInterface $builder, array $options) 
{ 
$builder 
->add('beds', 'choice', [ 
    'choices' => [ 
     '1' => '1', 
     '2' => '2', 
     '3' => '3', 
     '4' => '4', 
     '5' => '5', 
     '6' => '6', 
     '7' => '7', 
     '8' => '8', 
     '9' => '9+', 
    ], 
    'placeholder' => '', 
]) 
->add('baths', 'choice', [ 
    'choices' => [ 
     '1' => '1', 
     '2' => '2', 
     '3' => '3', 
     '4' => '4', 
     '5' => '5', 
     '6' => '6', 
     '7' => '7', 
     '8' => '8', 
     '9' => '9+', 
    ], 
    'placeholder' => '', 
]) 
->add('storey', 'choice', [ 
    'choices' => [ 
     '1' => '1', 
     '2' => '2', 
     '3' => '3', 
     '4' => '4', 
     '5' => '5', 
     '6' => '6', 
     '7' => '7', 
     '8' => '8', 
     '9' => '9+', 
    ], 
    'placeholder' => '', 
    'required' => false, 
]) 
->add('title') 
->add('body') 
->add('password', 'repeated', [ 
    'type' => 'password', 
    'invalid_message' => 'The password fields must match.', 
    'options' => array('attr' => array('class' => 'password-field')), 
    'required' => true, 
    'first_options' => array('label' => 'Password'), 
    'second_options' => array('label' => 'Repeat Password'), 
]) 
->add('province', 'entity', [ 
    'class' => 'AppBundle:Province', 
    'property' => 'name', 
    'placeholder' => '' 
]) 
->add('activity', 'entity', [ 
    'class' => 'AppBundle:Activity', 
    'property' => 'name', 
    'placeholder' => '' 
]) 
->add('unit', 'entity', [ 
    'class' => 'AppBundle:Unit', 
    'property' => 'name', 
    'placeholder' => '' 
]) 
->add('direction', 'entity', [ 
    'class' => 'AppBundle:Direction', 
    'property' => 'name', 
    'placeholder' => '', 
    'required' => false 
]) 
->add('legal', 'entity', [ 
    'class' => 'AppBundle:Legal', 
    'property' => 'name', 
    'placeholder' => '', 
    'required' => false 
]) 
->add('images', 'collection', [ 
    'type' => new PropertyImageType(), 
    'allow_add' => true, 
    'allow_delete' => true 
]) 
->add('amenities', 'entity', [ 
    'class' => 'AppBundle:Amenity', 
    'property' => 'name', 
    'expanded' => true, 
    'multiple' => true, 
    'query_builder' => function (EntityRepository $repository) { 
     return $repository->createQueryBuilder('a') 
      ->from('AppBundle:Amenity', 'amenity') 
      ->where('a.type = 1'); 
    } 
]); 

И я использую EventSubscriber, чтобы добавить поле динамически

$builder->addEventSubscriber(new AddDistrictFieldSubscriber()) 
    ->addEventSubscriber(new AddStreetFieldSubscriber()) 
    ->addEventSubscriber(new AddWardFieldSubscriber()) 
    ->addEventSubscriber(new AddProjectFieldSubscriber()); 

class AddDistrictFieldSubscriber implements EventSubscriberInterface 
{ 

    /** 
    * Returns an array of event names this subscriber wants to listen to. 
    * 
    * The array keys are event names and the value can be: 
    * 
    * * The method name to call (priority defaults to 0) 
    * * An array composed of the method name to call and the priority 
    * * An array of arrays composed of the method names to call and respective 
    * priorities, or 0 if unset 
    * 
    * For instance: 
    * 
    * * array('eventName' => 'methodName') 
    * * array('eventName' => array('methodName', $priority)) 
    * * array('eventName' => array(array('methodName1', $priority), array('methodName2')) 
    * 
    * @return array The event names to listen to 
    * 
    * @api 
    */ 
    public static function getSubscribedEvents() 
    { 
     return [ 
      FormEvents::PRE_SET_DATA => 'preSetData', 
      FormEvents::PRE_SUBMIT => 'preSubmit', 
     ]; 
    } 

    public function preSetData(FormEvent $event) 
    { 
     $data = $event->getData(); 
     $form = $event->getForm(); 

     $province = $data->getProvince(); 
     $districts = $province === null ? [] : $province->getDistricts(); 

     $form->add('district', 'entity', [ 
      'class' => 'AppBundle:District', 
      'property' => 'name', 
      'placeholder' => '', 
      'choices' => $districts, 
     ]); 
    } 

    public function preSubmit(FormEvent $event) 
    { 
     $data = $event->getData(); 
     $form = $event->getForm(); 

     $province = array_key_exists('province', $data) ? $data['province'] : null; 

     $form->add('district', 'entity', [ 
      'class' => 'AppBundle:District', 
      'property' => 'name', 
      'placeholder' => '', 
      'query_builder' => function (EntityRepository $repository) use ($province) { 
       return $repository->createQueryBuilder('d') 
        ->from('AppBundle:District', 'district') 
        ->where('district.province = :province') 
        ->setParameter('province', $province); 
      } 
     ]); 
    } 
} 

class AddStreetFieldSubscriber implements EventSubscriberInterface 
{ 

    /** 
    * Returns an array of event names this subscriber wants to listen to. 
    * 
    * The array keys are event names and the value can be: 
    * 
    * * The method name to call (priority defaults to 0) 
    * * An array composed of the method name to call and the priority 
    * * An array of arrays composed of the method names to call and respective 
    * priorities, or 0 if unset 
    * 
    * For instance: 
    * 
    * * array('eventName' => 'methodName') 
    * * array('eventName' => array('methodName', $priority)) 
    * * array('eventName' => array(array('methodName1', $priority), array('methodName2')) 
    * 
    * @return array The event names to listen to 
    * 
    * @api 
    */ 
    public static function getSubscribedEvents() 
    { 
     return [ 
      FormEvents::PRE_SET_DATA => 'preSetData', 
      FormEvents::PRE_SUBMIT => 'preSubmit', 
     ]; 
    } 

    public function preSetData(FormEvent $event) 
    { 
     $data = $event->getData(); 
     $form = $event->getForm(); 

     $district = $data->getDistrict(); 
     $streets = $district === null ? [] : $district->getStreets(); 

     $form->add('street', 'entity', [ 
      'class' => 'AppBundle:Street', 
      'property' => 'name', 
      'placeholder' => '', 
      'choices' => $streets, 
      'required' => false, 
     ]); 
    } 

    public function preSubmit(FormEvent $event) 
    { 
     $data = $event->getData(); 
     $form = $event->getForm(); 

     $district = array_key_exists('district', $data) ? $data['district'] : null; 

     $form->add('street', 'entity', [ 
      'class' => 'AppBundle:Street', 
      'property' => 'name', 
      'placeholder' => '', 
      'query_builder' => function (EntityRepository $repository) use ($district) { 
       return $repository->createQueryBuilder('s') 
        ->from('AppBundle:Street', 'street') 
        ->where('street.district = :district') 
        ->setParameter('district', $district); 
      } 
     ]); 
    } 
} 

Базы данных таблицы: - Область: идентификатор - имя (70 записей) - район: id - province_id - prefix - name (700 записей) - улица: id - district_id - prefix - name (17000 записей) - ward: id - district_id - prefix - name (11000 записей) ... и еще несколько таблиц

+0

Вы можете попытаться увеличить лимит памяти в php.ini memory_limit = 1024M или вы можете сделать ini_set («memory_limit», '1024M «); –

+0

У моего сервера не так много памяти, я думаю, что когда handleRequest() проверяет сущности поля, он должен запрашивать много данных из db – Geany

+0

Что-то о проверке относительно списка выбора, сопоставленного с db: если попытаться загрузите огромный набор данных. Пожалуйста, напишите больше кода для проверки с идеей о размере таблицы вашей базы данных объекта. – Matteo

ответ

0

После отладки каждого поля в форме, в конце концов я нашел проблему в построитель запросов в preSubmit()

$form->add('district', 'entity', [ 
    'class' => 'AppBundle:District', 
    'property' => 'name', 
    'placeholder' => '', 
    'query_builder' => function (EntityRepository $repository) use ($province) { 
     return $repository->createQueryBuilder('d') 
      ->from('AppBundle:District', 'district') 
      ->where('district.province = :province') 
      ->setParameter('province', $province); 
    } 
]); 

$form->add('street', 'entity', [ 
    'class' => 'AppBundle:Street', 
    'property' => 'name', 
    'placeholder' => '', 
    'query_builder' => function (EntityRepository $repository) use ($district) { 
     return $repository->createQueryBuilder('s') 
      ->from('AppBundle:Street', 'street') 
      ->where('street.district = :district') 
      ->setParameter('district', $district); 
    } 
]); 

Я использую разностный псевдоним, так учение получит все записи в каждой таблице -> исчерпана память. Так просто использовать один и тот же псевдоним или удалить из() в построитель запросов;)

$form->add('district', 'entity', [ 
    'class' => 'AppBundle:District', 
    'property' => 'name', 
    'placeholder' => '', 
    'query_builder' => function (EntityRepository $repository) use ($province) { 
     return $repository->createQueryBuilder('district') 
      ->where('district.province = :province') 
      ->setParameter('province', $province); 
    } 
]); 
Смежные вопросы