Crash21 Crash21 - 5 months ago 11
PHP Question

Symfony Forms Inject object

I have a Symfony Form Type and I want to inject on it another form I have Created:

$form = $this->createFormBuilder();
$form->add('quantity', NumberType::class);
$form->add('options', ProductOptionType::class);
$form->add('notes', TextareaType::class, ]);


ProductOptionType is another type I have created but on this type I inject on constructor the current product so I know then what available options this product has in order to add in the form (ie color, size etc).

class ProductOptionType extends AbstractType
{
private $productOptions;

public function __construct(Product $product)
{
$this->productOptions = $product->getOptions();
}

public function buildForm(FormBuilderInterface $builder, array $options)
{
foreach ($this->productOptions as $option) {
$builder->add($option->getId(), ChoiceType::class, [
'choices' => $option->getChoicesForForm(),
'label' => $option->getName()
]);
}
}
}


The Problem is how to pass the constructor here???

$form->add('options', ProductOptionType::class);


The above throws contstructor none error as it instantiates the type without passign to the injector the product.

Also this one throws exception:

$form->add('options', new ProductOptionType($product));


Because it expects a string and not an object.

Answer

You could pass extra data with the options

class ProductOptionType extends AbstractType
{    

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $productOptions = $options['productOptions'];

        foreach ($productOptions as $option) {
            $builder->add($option->getId(), ChoiceType::class, [
                'choices' => $option->getChoicesForForm(),
                'label' => $option->getName()
            ]);
        }
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        // you can define a required option field for work
        $resolver->setRequired([
             'productOptions',
         ]);
         // ...
         // You could specify which type of class is supported
        $resolver->setAllowedTypes([
             'user' => ProductOptions:class,
         ]);
    }

}

Then use it in the form creation as follow:

$form->add('options', ProductOptionType::class, ['productOptions' => $product]);

Hope this help

Comments