Skip to content

Remove some container injections in favor of service locators #21625

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 28, 2017

Conversation

chalasr
Copy link
Member

@chalasr chalasr commented Feb 15, 2017

Q A
Branch? master
Bug fix? no
New feature? yes
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets #21553 (comment)
License MIT
Doc PR n/a

@chalasr chalasr force-pushed the remove-container-injections branch 4 times, most recently from 6d9025c to bee8bac Compare February 16, 2017 12:53
} else {
$logger = null;
}
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestions to make this deprecation better are welcomed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing type check when the 2nd arg is not an array (LoggerInterface|null)

@chalasr chalasr force-pushed the remove-container-injections branch from bee8bac to 404200a Compare February 16, 2017 13:03
$this->mapping = $mapping;
// BC 3.x, to be removed in 4.0, re-adding the LoggerInterface typehint to the $logger argument
if (is_array($logger)) {
@trigger_error(sprintf('The second argument of %s() is deprecated since symfony 3.3 and will be removed, passing something else than a %s instance will trigger an error in 4.0.', __METHOD__, LoggerInterface::class), E_USER_DEPRECATED);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/symfony 3.3/Symfony 3.3/


/**
* @group legacy
* @expectedDeprecation The second argument of Symfony\Bundle\TwigBundle\ContainerAwareRuntimeLoader::__construct() is deprecated since symfony 3.3 and will be removed, passing something else than a Psr\Log\LoggerInterface instance will trigger an error in 4.0.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/symfony 3.3/Symfony 3.3/

@chalasr chalasr force-pushed the remove-container-injections branch 2 times, most recently from 1d3ef15 to 2675b30 Compare February 16, 2017 14:35
@@ -11,7 +11,7 @@

<services>
<service id="fragment.handler" class="Symfony\Component\HttpKernel\DependencyInjection\LazyLoadingFragmentHandler">
<argument type="service" id="service_container" />
<argument /> <!-- fragment renderer locator -->
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can do getter injection on this one very easily!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are you talking about getSession() in the session listener instead? If no, could you elaborate?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, that's what I mean

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@chalasr yeah, this seems to be on the wrong service.

for the SessionListener, I'm in favor of leaving the FrameworkBundle class unchanged, deprecating it, and using getter injection on the component class itself.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The FrameworkBundle class was just doing getter injection implemented manually.

Copy link
Member Author

@chalasr chalasr Feb 17, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry, added as last commit a4a4b3b

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ReflectionClass::newInstanceWithoutConstructor breaks on it

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is newInstanceWithoutConstructor called inside ContainerBuilder or inside the dumped container?

Copy link
Member

@stof stof Feb 17, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nicolas-grekas in the compiler pass, when registering the subscriber in a dummy event dispatcher to collect subscribed events and register it lazily.

however, I don't even understand why we do this: In Symfony stable releases, the ContainerAwareEventDispatcher calls the static getSubscribedEvents statically. We don't need an instance for that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's because of https://github.com/symfony/symfony/blob/master/src/Symfony/Component/EventDispatcher/EventDispatcher.php#L127 which requires an instance
but this PR now has a fix you will like :)

$this->mapping = $mapping;
// BC 3.x, to be removed in 4.0, re-adding the LoggerInterface typehint to the $logger argument
if (is_array($logger)) {
@trigger_error(sprintf('The second argument of %s() is deprecated since version 3.3 and will be removed, passing something else than a %s instance will trigger an error in 4.0.', __METHOD__, LoggerInterface::class), E_USER_DEPRECATED);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"The $mapping argument..." (the 2nd won't be removed since it will expect the logger)

} else {
$logger = null;
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing type check when the 2nd arg is not an array (LoggerInterface|null)

if (is_array($logger)) {
@trigger_error(sprintf('The second argument of %s() is deprecated since version 3.3 and will be removed, passing something else than a %s instance will trigger an error in 4.0.', __METHOD__, LoggerInterface::class), E_USER_DEPRECATED);

if (2 < func_num_args() && func_get_arg(3) instanceof LoggerInterface) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not needed if the constructor signature is changed to
__construct(ContainerInterface $container, $mapping = null, LoggerInterface $logger = null)

}

/**
* {@inheritdoc}
*/
public function load($class)
{
if (isset($this->mapping[$class])) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when $mapping is provided as an array, we should still use it

@@ -42,23 +42,24 @@ public function __construct(ContainerInterface $container, RequestStack $request
/**
* Adds a service as a fragment renderer.
*
* @deprecated since version 3.3, to be removed in 4.0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should always be put last, after @param

*/
public function testSecondConstructorArgumentIsDeprecated()
{
$loader = new ContainerAwareRuntimeLoader($this->getMockBuilder(ContainerInterface::class)->getMock(), array());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you also need to test that the existing behavior (using a mapping) keeps working. Copy the existing testLoad method for that.

* @param string $name The service name
* @param string $renderer The render service id
*/
public function addRendererService($name, $renderer)
{
$this->rendererIds[$name] = $renderer;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removing the implementation is wrong. It means that the feature does not work anymore, which is a BC break

if (isset($this->rendererIds[$renderer])) {
$this->addRenderer($this->container->get($this->rendererIds[$renderer]));

unset($this->rendererIds[$renderer]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you must keep using $this->rendererIds for the BC layer

public function testAddRendererServiceIsDeprecated()
{
$handler = new LazyLoadingFragmentHandler($this->getMockBuilder('Psr\Container\ContainerInterface')->getMock(), $this->getMockBuilder('Symfony\Component\HttpFoundation\RequestStack')->getMock());
$handler->addRendererService('foo', 'bar');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you must keep the existing tests of the class here, to ensure that the 3.2 way of using the class keeps working

@@ -14,6 +14,8 @@
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We tend to sort new use statements (without touching existing ones, to avoid a nightmare when merging branches). So please move this one at the beginning

@@ -11,8 +11,8 @@

namespace Symfony\Bundle\TwigBundle;

use Psr\Container\ContainerInterface;
use Psr\Log\LoggerInterface;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fabpot as this class now depends only on PSR classes, should we add it in Twig itself ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, that's probably a good idea.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok I'll do a twig PR in parallel.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stof This means deprecating this class and bump the twig requirement to 2.x in TwigBundle to use the twig class instead, right?

Copy link
Member Author

@chalasr chalasr Feb 17, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated to use the twig class, it will break tests until twigphp/Twig#2401 is merged and released

@chalasr
Copy link
Member Author

chalasr commented Feb 17, 2017

Thanks for the reviews.

Status: needs work

@@ -21,7 +21,7 @@
"symfony/twig-bridge": "^3.2.1",
"symfony/http-foundation": "~2.8|~3.0",
"symfony/http-kernel": "~2.8.16|~3.1.9|^3.2.2",
"twig/twig": "~1.28|~2.0"
"twig/twig": "~2.2"
Copy link
Member

@fabpot fabpot Feb 17, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's not possible. We cannot drop support for Twig 1.x. But the good news is that we are still maintaining Twig 1.x and 2.x. So the constraint can be ^1.32|^2.2.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

constraint fixed

@chalasr chalasr force-pushed the remove-container-injections branch from c89b788 to 097856e Compare February 17, 2017 18:34
@@ -21,7 +21,7 @@
"symfony/twig-bridge": "^3.2.1",
"symfony/http-foundation": "~2.8|~3.0",
"symfony/http-kernel": "~2.8.16|~3.1.9|^3.2.2",
"twig/twig": "~1.28|~2.0"
"twig/twig": "^1.29|^2.2"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, should be 1.32.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

@chalasr chalasr force-pushed the remove-container-injections branch 3 times, most recently from a4a4b3b to 550f877 Compare February 17, 2017 19:03
fabpot added a commit to twigphp/Twig that referenced this pull request Feb 17, 2017
This PR was merged into the 1.x branch.

Discussion
----------

Add ContainerRuntimeLoader

Next to symfony/symfony#21625 (comment)

Commits
-------

964a51b Add ContainerRuntimeLoader
@chalasr chalasr force-pushed the remove-container-injections branch 3 times, most recently from 85c30a0 to 961234e Compare February 17, 2017 20:11
@chalasr chalasr force-pushed the remove-container-injections branch 2 times, most recently from ce55cd6 to 2e5f25e Compare February 26, 2017 10:15
@chalasr chalasr changed the title Remove some container injections in favor of service locators/getter injection Remove some container injections in favor of service locators Feb 26, 2017
@chalasr chalasr force-pushed the remove-container-injections branch 2 times, most recently from c37ac4d to f891b7e Compare February 26, 2017 10:25
@chalasr
Copy link
Member Author

chalasr commented Feb 26, 2017

*SessionListener deprecated and moved to HttpKernel, note that the naming change was required.
Status: needs review

@chalasr chalasr force-pushed the remove-container-injections branch 4 times, most recently from 7d6f58f to 23662b2 Compare February 26, 2017 12:50
@chalasr chalasr force-pushed the remove-container-injections branch from 23662b2 to 8293b75 Compare February 26, 2017 13:01
fabpot added a commit that referenced this pull request Feb 26, 2017
…ument type (chalasr)

This PR was merged into the 3.3-dev branch.

Discussion
----------

[DI] Remove experimental status from service-locator argument type

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #21625 (comment), #21625 (comment), #21710
| License       | MIT

The `service-locator` argument type is not controversial to me. We know its scope, nothing really surprising, just a map of services to be lazily loaded like `iterator` is (which is not experimental) but keyed.
About its api, it's just PSR-11 restricted to objects, nothing that can't be changed safely in the future.

As stated in #21625 (comment), it proven its usefulness already. I think what we were looking for by flagging it experimental is just to see it in action, we've 3 opened PRs for that (#21625, #21690, #21730).

This allows introducing deprecations for making use of the feature in the core, thus unlocks #21625 and #21690.

Commits
-------

46dc47a [DI] Remove experimental status from service-locator argument type
symfony-splitter pushed a commit to symfony/dependency-injection that referenced this pull request Feb 26, 2017
…ument type (chalasr)

This PR was merged into the 3.3-dev branch.

Discussion
----------

[DI] Remove experimental status from service-locator argument type

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | symfony/symfony#21625 (comment), symfony/symfony#21625 (comment), #21710
| License       | MIT

The `service-locator` argument type is not controversial to me. We know its scope, nothing really surprising, just a map of services to be lazily loaded like `iterator` is (which is not experimental) but keyed.
About its api, it's just PSR-11 restricted to objects, nothing that can't be changed safely in the future.

As stated in symfony/symfony#21625 (comment), it proven its usefulness already. I think what we were looking for by flagging it experimental is just to see it in action, we've 3 opened PRs for that (#21625, #21690, #21730).

This allows introducing deprecations for making use of the feature in the core, thus unlocks #21625 and #21690.

Commits
-------

46dc47af11 [DI] Remove experimental status from service-locator argument type
Copy link
Member

@nicolas-grekas nicolas-grekas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@fabpot
Copy link
Member

fabpot commented Feb 28, 2017

Thank you @chalasr.

@fabpot fabpot merged commit 8293b75 into symfony:master Feb 28, 2017
fabpot added a commit that referenced this pull request Feb 28, 2017
…ocators (nicolas-grekas, chalasr)

This PR was merged into the 3.3-dev branch.

Discussion
----------

Remove some container injections in favor of service locators

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #21553 (comment)
| License       | MIT
| Doc PR        | n/a

Commits
-------

8293b75 Replace some container injections by service locators
0be9ea8 [EventDispatcher] Fix abstract event subscribers registration
@fabpot
Copy link
Member

fabpot commented Feb 28, 2017

This PR breaks the test suite of SensioFrameworkExtraBundle. @chalasr Can you have a look at it?

@chalasr
Copy link
Member Author

chalasr commented Feb 28, 2017

@fabpot see #21794

nicolas-grekas added a commit that referenced this pull request Feb 28, 2017
…ence values (chalasr)

This PR was merged into the 3.3-dev branch.

Discussion
----------

[DI] Fix ServiceLocatorArgument::setValues() for non-reference values

| Q             | A
| ------------- | ---
| Branch?       | master
| Fixed tickets | #21625 (comment)
| Tests pass?   | yes
| License       | MIT

`ResolveInvalidReferencesPass` [calls `setValues()`](https://github.com/symfony/symfony/blob/master/src/Symfony/Component/DependencyInjection/Compiler/ResolveInvalidReferencesPass.php#L91) with resolved invalid reference (null), the `Reference` type check should occurs at construction only.

Commits
-------

256b836 [DI] Fix ServiceLocatorArgument::setValues() for non-reference values
@fabpot fabpot mentioned this pull request May 1, 2017
nicolas-grekas added a commit that referenced this pull request May 21, 2017
…sses (chalasr)

This PR was merged into the 4.0-dev branch.

Discussion
----------

Remove deprecated container injections and compiler passes

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | no
| BC breaks?    | yes
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | ~~#21451 #21625 #21284 #22010~~ #22805
| License       | MIT
| Doc PR        | n/a

Commits
-------

16a2fcf Remove deprecated container injections and compiler passes
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants