-
-
Save pjedrzejewski/a9d6728410040fc838fd to your computer and use it in GitHub Desktop.
| <?php | |
| class ResourceAutocompleteType extends AbstractType | |
| { | |
| // ... | |
| private $resourceName; | |
| public function __construct($resourceName) | |
| { | |
| $this->resourceName = $resourceName; | |
| } | |
| public function getName() | |
| { | |
| return sprintf('sylius_%s_autocomplete', $this->resourceName); | |
| } | |
| } | |
| // This allows us to generate form types: | |
| // sylius_product_autocomplete | |
| // sylius_customer_autocomplete | |
| // Expected DX: | |
| class MyCustomType extends AbstractType | |
| { | |
| public function buildForm(FormBuilderInterface $builder, array $options) | |
| { | |
| $builder | |
| ->add('products', 'sylius_product_autocomplete', array( | |
| 'multiple' => true, | |
| )) | |
| ; | |
| } | |
| } | |
| // In Symfony 3.0 we would need to: | |
| class ResourceAutocompleteType extends AbstractType | |
| { | |
| // ... | |
| public function configureOptions(OptionsResolver $resolver) | |
| { | |
| $resolver->setRequired(array('resource')); // etc. | |
| } | |
| public function getName() | |
| { | |
| return 'sylius_resource_autocomplete'; | |
| } | |
| } | |
| // Which results in following DX: | |
| class MyCustomType extends AbstractType | |
| { | |
| public function buildForm(FormBuilderInterface $builder, array $options) | |
| { | |
| $builder | |
| ->add('products', 'sylius_resource_autocomplete', array( | |
| 'resource' => 'sylius.product', | |
| 'multiple' => true, | |
| )) | |
| ; | |
| } | |
| } | |
| /* This also affects other aspects of DX and our implementation: | |
| * We can no longer generate the form types based on configuration; | |
| * We cannot easily pass dependencies to specific form types; | |
| * Developer (end-user of the bundles/app) cannot override a specific form type easily: | |
| Right now can override ``sylius_product_autocomplete`` to change all autocompletes across whole app. | |
| With forms without type names, he would need to override all forms using ResourceAutocompleteType::class and replace it with his own class etc. | |
| */ |
Hi Pawel! Unfortunately auto-generation of form types was never an officially supported feature. With some shortening, your type could be adapted to:
class MyCustomType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('products', AutocompleteType::class, array(
'resource' => Product::class,
'multiple' => true,
))
;
}
}This is pretty straight-forward and easy to use. Naming conflicts are now dealt with implicitly since you are importing the class name.
Developers can override your AutocompleteType entirely or add a type extension that is only activated if resource matches a certain class.
Dependencies should be passed in the DIC (as always).
@pjedrzejewski And what about using form type extensions to allow users to override Sylius form types? I think that is also the recommended way now to override form types in symfony 3.0. They live in a seperate service, and injecting stuff is easier, instead of altering the definition in a compiler pass.
@pjedrzejewski how can the container eventually resolve sprintf('sylius_%s_autocomplete', $this->resourceName) to sylius_product_autocomplete? There should be some extra configuration to handle that right? That same configuration (e.g. the Product::class) should in my opinion be handled via the options, as @webmozart mentions in https://gist.github.com/pjedrzejewski/a9d6728410040fc838fd#gistcomment-1647210
You could also create one Type extending the ResourceAutocompleteType per category which might be a clean solution as well, depending on how many resource types you have.
Otherwise the option is also a feasible solution, upgrading can be some pain.