diff --git a/DependencyInjection/AdmingeneratorGeneratorExtension.php b/DependencyInjection/AdmingeneratorGeneratorExtension.php index 85cf75bc..f288aa37 100644 --- a/DependencyInjection/AdmingeneratorGeneratorExtension.php +++ b/DependencyInjection/AdmingeneratorGeneratorExtension.php @@ -269,7 +269,8 @@ private function registerGeneratedFormsAsServices(ContainerBuilder $container) private function registerFormsServicesFromGenerator(array $generatorParameters, array $builders, ContainerBuilder $container) { $modelParts = explode('\\', $generatorParameters['model']); - $model = array_pop($modelParts); + $model = strtolower(array_pop($modelParts)); // @TODO: BC Support, remove it starting from v.3.0.0 + $fullQualifiedNormalizedModelName = strtolower(str_replace('\\', '_', ltrim($generatorParameters['model'], '\\'))); $formsBundleNamespace = sprintf( '%s%s\\Form\\Type\\%s', $generatorParameters['namespace_prefix'] ? $generatorParameters['namespace_prefix'] . '\\' : '', @@ -284,7 +285,8 @@ private function registerFormsServicesFromGenerator(array $generatorParameters, ->addMethodCall('setAuthorizationChecker', array($authorizationCheckerServiceReference)) ->addTag('form.type'); - $container->setDefinition('admingen_generator_' . strtolower($model) . '_new', $newDefinition); + $container->setDefinition(($id = 'admingen_generator_' . $fullQualifiedNormalizedModelName . '_new'), $newDefinition); + $container->setAlias('admingen_generator_' . $model . '_new', $id); } if (in_array('edit', $builders)) { @@ -293,7 +295,8 @@ private function registerFormsServicesFromGenerator(array $generatorParameters, ->addMethodCall('setAuthorizationChecker', array($authorizationCheckerServiceReference)) ->addTag('form.type'); - $container->setDefinition('admingen_generator_' . strtolower($model) . '_edit', $editDefinition); + $container->setDefinition(($id = 'admingen_generator_' . $fullQualifiedNormalizedModelName . '_edit'), $editDefinition); + $container->setAlias('admingen_generator_' . $model . '_edit', $id); } if (in_array('list', $builders) || in_array('nested_list', $builders)) { @@ -302,7 +305,8 @@ private function registerFormsServicesFromGenerator(array $generatorParameters, ->addMethodCall('setAuthorizationChecker', array($authorizationCheckerServiceReference)) ->addTag('form.type'); - $container->setDefinition('admingen_generator_' . strtolower($model) . '_filter', $filterDefinition); + $container->setDefinition(($id = 'admingen_generator_' . $fullQualifiedNormalizedModelName . '_filter'), $filterDefinition); + $container->setAlias('admingen_generator_' . $model . '_filter', $id); } } diff --git a/Resources/doc/cookbook/inject-services-into-form-types.md b/Resources/doc/cookbook/inject-services-into-form-types.md new file mode 100644 index 00000000..87759f76 --- /dev/null +++ b/Resources/doc/cookbook/inject-services-into-form-types.md @@ -0,0 +1,98 @@ +# Inject services into form types + +Sometimes it will be necessary for you to injecting additional services +into generated form types. + +GeneratorBundle registers all generated form types into service container +within bundle extension +(see `\Admingenerator\GeneratorBundle\DependencyInjection\AdmingeneratorGeneratorExtension::registerFormsServicesFromGenerator()` +for implementation details). + +Form types service names are generated according to the following pattern: +- For **NewType**: `admingen_generator_[UNDERSCORED_MODEL_FQCN]_new` +- For **EditType**: `admingen_generator_[UNDERSCORED_MODEL_FQCN]_new` +- For **FiltersType**: `admingen_generator_[UNDERSCORED_MODEL_FQCN]_filter` + +Illustrative example to understand service name pattern: if model type FQCN +is `\My\Example\Entity`, generated form type service name for new type +would be: `admingen_generator_my_example_entity_new`. + +All auto-registered form type services contains proper service tag `form.type`, +as well as setter definition which injects necessary `security.authorization_checker` +service. + +**BC NOTE:** *Up to version 2.1.1 service names were generated by using +only class name without namespaces. Considering our previous given example, +generated service name would be `admingen_generator_entity_new`. This was +a bug in previous versions, which was fixed for versions above 2.1.1. However, +in order not to inflict BC break, new service name patterns are aliased +with old service names. From version 3.0.0 this BC support will be removed, +you should use new service name pattern rule for referencing your form types +in service container.* + +Now, when you are aware of the method of how generated form types are +registered in service container, you are able to modify those service +definitions, and most common use case scenario is to inject additional +dependencies. + +Here are two proposed methods: + +## Method 1: Create your own compiler pass and modify generated service definition + +In your application bundle, you can register your own compiler pass, +require your form type service definition and inject additional services, +example: + + class MyAppCompilerPass implements CompilerPassInterface + { + public function process(ContainerBuilder $container) + { + if ($container->hasDefinition('admingen_generator_my_example_entity_new')) { + $container + ->getDefinition('admingen_generator_my_example_entity_new') + ->setArguments( [ UTILIZING CONSTRUCTOR INJECTION ] ) + ->addMethodCall( [ UTILIZING SETTER INJECTION ] ); + } + } + } + +This is most preferable way, however, if you have a lot of forms for which +you have to modify service definitions, this can be time consuming. + +## Method 2: "Magic" injection by using `runopencode\traitor-bundle` and traits + +You can use third party bundle [`runopencode\traitor-bundle`](https://github.com/RunOpenCode/traitor-bundle) +which allows you to inject additional services to your auto-generated +forms with just `use trait` statement in form type class, and mentioned +bundle will take care of injecting appropriate service, example: + + namespace MyBundle\Form\Type\MyModel; + + use Admingenerated\MyBundle\Form\MyModelType\NewType as BaseNewType + + class NewType extends BaseNewType + { + use \Psr\Log\LoggerAwareTrait; + } + +In example given above, bundle will figure out that you are requiring for +a `logger` service, which will be injected via setter injection. + +This is very easy and productive way to inject additional services into +form types, you do not have to care about generated service names and you +do not have to create your own compiler pass, nor additionally code injection +logic. + +However, it is a *"magic"* injection which breaks Symfony convention of +how service injection should be registered. + +It is strongly advised to read fully and carefully documentation of +`runopencode\traitor-bundle` before making decision of its usage, authors +have explained in details how bundle works, and what are *"pros"* and +*"cons"* of its usage, so you can make informed decision and choose approach +which suits your needs best. + + + + + \ No newline at end of file diff --git a/Resources/doc/documentation.md b/Resources/doc/documentation.md index 6d0198a3..5f7bf285 100644 --- a/Resources/doc/documentation.md +++ b/Resources/doc/documentation.md @@ -33,6 +33,7 @@ we encourage you to update to latest build. If you're getting errors or have tro - [Multiple entity managers (Doctrine)][cookbook-em] - [View parameters][cookbook-view-parameters] - [Modal with fields][modal-with-fields] + - [Inject services into form types][inject-services-into-form-types] 5. Support and contribution - [Submitting issues][support-issues] - [Contributing code][support-contributing] @@ -92,3 +93,4 @@ Below are some screenshots of our very simple demo project. [cookbook-menu]: cookbook/knp-menu.md [cookbook-view-parameters]: cookbook/view-parameters.md [modal-with-fields]: cookbook/modal-with-fields.md +[inject-services-into-form-types]: cookbook/inject-services-into-form-types.md diff --git a/UPGRADE.MD b/UPGRADE.MD index 616d1d85..40eb4be2 100644 --- a/UPGRADE.MD +++ b/UPGRADE.MD @@ -6,6 +6,13 @@ This page contains all upgrade notes since the release of the stable 2.0.0 version. +## Current `master` branch + +- Fixed [#285](https://github.com/symfony2admingenerator/GeneratorBundle/issues/285): added cookbook entry regarding injection + of additional services in form types. Documented method of registration of auto generated form types in service container. +- Fixed [#288](https://github.com/symfony2admingenerator/GeneratorBundle/issues/288): generated form types now have unique + service name. Old naming is aliased to new service name in order not to have BC break. + ## 2.1.0 - Fixed [#245](https://github.com/symfony2admingenerator/GeneratorBundle/issues/245): KnpMenuBundle usage is now optional.