-
-
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.