Я задал аналогичный вопрос, но я думаю, что это вызвало путаницу, поэтому я решил спросить в этом посте с размытой версией.
Я хочу, чтобы печатать все поля из двух разных объектов в одной веб-форме, BOTH TYPE . Вот и все.
Примечание. Я попытался использовать ключевые слова entity
и collection
в типе формы ( BOTH TYPE ), но веточка не отгоняет ничего. Постоянно получаю; Method "brand" OR "car" for object does not exist in twig line whatever....
Отношения: 1 Brand
имеет N Cars
. один ко многим
Я прочитал «Как вставить коллекцию форм», «Тип поля сущности» и «Тип поля коллекции», но все, что я сделал, не помогло.
BRAND ENTITY
namespace Car\BrandBundle\Entity; use Doctrine\ORM\Mapping as ORM; use Doctrine\Common\Collections\ArrayCollection; class BrandEntity { protected $id; protected $name; protected $origin; /** * @ORM\OneToMany(targetEntity = "CarEntity", mappedBy = "brand") * @var object $car */ protected $car; /** * Constructor. */ public function __construct() { $this->car = new ArrayCollection(); } }
АВТОМОБИЛЬ
namespace Car\BrandBundle\Entity; use Doctrine\ORM\Mapping as ORM; class CarEntity { protected $id; protected $model; protected $price; /** * @ORM\ManyToOne(targetEntity="BrandEntity", inversedBy="car") * @ORM\JoinColumn(name="brand_id", referencedColumnName="id") * @var object $brand */ protected $brand; }
ТИП БРЕНДА
namespace Car\BrandBundle\Form\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class BrandType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->setAction($options['action']) ->setMethod('POST') ->add('name', 'text', array('label' => 'Name')) ->add('origin', 'text', array('label' => 'Origin')) ->add('button', 'submit', array('label' => 'Add')) ; } public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'data_class' => 'Car\BrandBundle\Entity\BrandEntity') ); } public function getName() { return 'brand'; } }
ТИП АВТОМОБИЛЯ
namespace Car\BrandBundle\Form\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class CarType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->setAction($options['action']) ->setMethod('POST') ->add('model', 'text', array('label' => 'Model')) ->add('price', 'text', array('label' => 'Price')) ->add('button', 'submit', array('label' => 'Add')) ; } public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'data_class' => 'Car\BrandBundle\Entity\CarEntity') ); } public function getName() { return 'car'; } }
————————————————– ——————-
——– Этот раздел – тот, который я пытаюсь заставить его работать ——
————————————————– ——————-
ОБЩИЙ ТИП
namespace Car\BrandBundle\Form\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Test\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class BothType extends AbstractType { public function builder(FormBuilderInterface $builder, array $options) { $builder ->setAction($options['action']) ->setMethod('POST') ->add('brand', 'collection', array('type' => new BrandType())) ->add('car', 'collection', array('type' => new CarType())) ->add('button', 'submit', array('label' => 'Add')) ; } public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'data_class' => 'Car\BrandBundle\Entity\BrandEntity', 'cascade_validation' => true )); } public function getName() { return 'both'; } }
КОНТРОЛЛЕР
namespace Car\BrandBundle\Controller; use Car\BrandBundle\Form\Type\BothType; use Symfony\Bundle\FrameworkBundle\Controller\Controller; class BothController extends Controller { public function indexAction() { $form = $this->createForm(new BothType(), null, array('action' => $this->generateUrl('bothCreate')));; return $this->render('CarBrandBundle:Default:both.html.twig', array('page' => 'Both', 'form' => $form->createView())); } }
TWIG
{% block body %} {{ form_label(form.brand.name) }} {{ form_widget(form.brand.name) }} {{ form_label(form.brand.origin) }} {{ form_widget(form.brand.origin) }} {{ form_label(form.car.model) }} {{ form_widget(form.car.model) }} {{ form_label(form.car.price) }} {{ form_widget(form.car.price) }} {% endblock %}
Используйте массив для объединения двух объектов в ваш контроллер.
$formData = array( 'brand' = new Brand(), 'car' => new Car(), ); $builder = $this->createFormBuilder($formData); $builder->add('brand',new BrandFormType()); $builder->add('car', new CarFormType()); $form = $builder->getForm(); ============================================================== If you really want to make a BothType then just get rid of that collection type. class BothType extends AbstractType { public function builder(FormBuilderInterface $builder, array $options) { $builder ->setAction($options['action']) ->setMethod('POST') ->add('brand', new BrandType()) ->add('car', new CarType()) ->add('button', 'submit', array('label' => 'Add')) ; } // Controller $form = $this->createForm(new BothType(), $formData
сбор используется, когда у вас есть несколько экземпляров одного и того же типа сущности.
Кстати, создание классов для каждой составной формы может быстро вызвать взрыв типов форм. Поэтому, если вы не планируете повторно использовать ваш BothFormType среди нескольких контроллеров, я бы предложил просто построить его прямо внутри контроллера.