Symfony2 Custom Field Type (Тип поля) для заполнения с помощью значений

Это следует из предыдущего вопроса Symfony2 Custom Type Type или Extension

Я пытаюсь прикрепить пользовательский тип поля для продукта в заказе. Поле имени будет содержать имя продукта, а поле идентификатора – идентификатор продукта.

Я использую FormEvents :: PRE_SET_DATA, чтобы попытаться заполнить данные, но он выдает ошибку, getData () возвращает Form \ Type \ ProductAutoCompleteType.

Как исправить код?

OrderType имеет следующее:

$builder->add('product', new Type\ProductAutoCompleteType(), array( 'data_class' => 'Acme\TestBundle\Entity\Product' )); 

ProductAutoCompleteType:

 class ProductAutoCompleteType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->add('name'); $builder ->add('id'); /* Turns out this is not needed any more $builder->addEventListener( FormEvents::PRE_SET_DATA, function (FormEvent $event) { $form = $event->getForm(); $product = $form->getData(); $form ->add('name', 'text', array('mapped' => false, 'data' => $product->getName())); } ); *// } public function setDefaultOptions(OptionsResolverInterface $resolver) { } public function getParent() { return 'form'; } public function getName() { return 'productAutoComplete'; } } 

обновленный

Ошибка: FatalErrorException: Ошибка: вызов функции-члена getProduct () для не-объекта в строке /var/www/symblog/src/Acme/TestBundle/Form/Type/ProductAutoCompleteType.php 26

контроллер

  $em = $this->getDoctrine()->getManager(); $order = $em->getRepository('AcmeTestBundle:Order')->find(6); $form = $this->createForm(new OrderType(), $order); 

Обновлено 2

После изменения поля [product] [id] и отправки формы я теперь получаю следующую ошибку, я предполагаю, что это потому, что имя поля [product] [id], а не [product]?

Ни свойство «id», ни один из методов «setId ()», « set ()» или «__call ()» не существуют и имеют открытый доступ в классе «Proxies__CG \ Acme \ TestBundle \ Entity \ Product».

Обновлено 3

Теперь у меня есть данные для контроллера, в моем контроллере на отправке я должен был добавить следующее, выглядит грязно, чтобы сделать проверку и прикрепить продукт таким образом, правильно ли это?

  $data = $request->request->get($form->getName()); if ($data['product']['id']) { $product = $em->getRepository('AcmeTestBundle:Product')->find($data['product']['id']); if ($product) { if ($product->getShop()->getId() != $order->getShop()->getId()) { $form->get('product')->get('name')->addError(new FormError('Invalid shop product')); } $form->getData()->setProduct($product); } else { $form->get('product')->get('name')->addError(new FormError('A product must be selected')); } } 

Related of "Symfony2 Custom Field Type (Тип поля) для заполнения с помощью значений"

Включение всей вашей логики в контроллер не является хорошей практикой. Ваши формы должны обрабатывать как можно больше, чтобы обеспечить повторное использование этих форм.

Если в запросе, который вы запрашиваете, нет связанного с ним продукта, тогда нормально, что $form->getData() возвращает значение null.

Отладочный совет:

Выведите значение $form->getData() для проверки объекта Product. Вывести значение $form->getParent()->getData() для проверки объекта Order из родительской формы.

Совет проверки:

Если продукт в этой форме может быть нулевым, убедитесь, что вы задали только данные поля имени, если продукт не является нулевым.

Совет:

Поскольку метод findBy в репозитории не будет автоматически включать связанный product , я рекомендую использовать QueryBuilder и сделать соединение. Пример в контроллере:

 $order = $em->getRepository('AcmeTestBundle:Order') ->createQueryBuilder('order') ->select('order, product') ->innerJoin('order.product', 'product') ->where('order.id = :order_id') ->setParameter('order_id', $order_id) ->getQuery() ->getOneOrNullResult(); 

Конечно, слишком много кода в вашем контроллере тоже невелик, поэтому, как только вы заработаете свой материал, создайте пользовательский репозиторий с помощью специального метода и переместите этот код там.

В вашей организации:

 /** * @Entity(repositoryClass="Acme\TestBundle\Repository\OrderRepository") */ class Order { 

В вашем репозитории

 class OrderRepository { public function findByIdWithProduct() { // $order = $this->createQueryBuilder... return $order; } }