Skip to content

[DependencyInjection] Deprecate autowiring service auto-registration #23712

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

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 51 additions & 7 deletions UPGRADE-3.4.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,50 @@ UPGRADE FROM 3.3 to 3.4
DependencyInjection
-------------------

* Autowiring service auto-registration is deprecated and won't be supported
in Symfony 4.0. Explicitly inject your dependencies or create services
whose ids are their fully-qualified class name.

Before:

```php
namespace App\Controller;

use App\Mailer;

class DefaultController
{
public function __construct(Mailer $mailer) {
// ...
}

// ...
}
```
```yml
services:
App\Controller\DefaultController:
autowire: true
```

After:

```php
// same PHP code
```
```yml
services:
App\Controller\DefaultController:
autowire: true

# or
# App\Controller\DefaultController:
# arguments: { $mailer: "@App\Mailer" }

App\Mailer:
autowire: true
 ```

* Top-level anonymous services in XML are deprecated and will throw an exception in Symfony 4.0.

Debug
Expand All @@ -30,13 +74,13 @@ FrameworkBundle
require symfony/stopwatch` in your `dev` environment.

* Using the `KERNEL_DIR` environment variable or the automatic guessing based
on the `phpunit.xml` / `phpunit.xml.dist` file location is deprecated since 3.4.
on the `phpunit.xml` / `phpunit.xml.dist` file location is deprecated since 3.4.
Set the `KERNEL_CLASS` environment variable to the fully-qualified class name
of your Kernel instead. Not setting the `KERNEL_CLASS` environment variable
will throw an exception on 4.0 unless you override the `KernelTestCase::createKernel()`
of your Kernel instead. Not setting the `KERNEL_CLASS` environment variable
will throw an exception on 4.0 unless you override the `KernelTestCase::createKernel()`
or `KernelTestCase::getKernelClass()` method.
* The `KernelTestCase::getPhpUnitXmlDir()` and `KernelTestCase::getPhpUnitCliConfigArgument()`

* The `KernelTestCase::getPhpUnitXmlDir()` and `KernelTestCase::getPhpUnitCliConfigArgument()`
methods are deprecated since 3.4 and will be removed in 4.0.

* The `--no-prefix` option of the `translation:update` command is deprecated and
Expand Down Expand Up @@ -83,7 +127,7 @@ TwigBridge
* deprecated the `Symfony\Bridge\Twig\Form\TwigRenderer` class, use the `FormRenderer`
class from the Form component instead

* deprecated `Symfony\Bridge\Twig\Command\DebugCommand::set/getTwigEnvironment` and the ability
* deprecated `Symfony\Bridge\Twig\Command\DebugCommand::set/getTwigEnvironment` and the ability
to pass a command name as first argument

* deprecated `Symfony\Bridge\Twig\Command\LintCommand::set/getTwigEnvironment` and the ability
Expand All @@ -95,7 +139,7 @@ TwigBundle
* deprecated the `Symfony\Bundle\TwigBundle\Command\DebugCommand` class, use the `DebugCommand`
class from the Twig bridge instead

* deprecated relying on the `ContainerAwareInterface` implementation for
* deprecated relying on the `ContainerAwareInterface` implementation for
`Symfony\Bundle\TwigBundle\Command\LintCommand`

Validator
Expand Down
54 changes: 49 additions & 5 deletions UPGRADE-4.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,50 @@ Debug
DependencyInjection
-------------------

* Autowiring service auto-registration is not supported anymore.
Explicitly inject your dependencies or create services whose ids are
their fully-qualified class name.

Before:

```php
namespace App\Controller;

use App\Mailer;

class DefaultController
{
public function __construct(Mailer $mailer) {
// ...
}

// ...
}
```
```yml
services:
App\Controller\DefaultController:
autowire: true
```

After:

```php
// same PHP code
```
```yml
services:
App\Controller\DefaultController:
autowire: true

# or
# App\Controller\DefaultController:
# arguments: { $mailer: "@App\Mailer" }

App\Mailer:
autowire: true
 ```

* Autowiring services based on the types they implement is not supported anymore. Rename (or alias) your services to their FQCN id to make them autowirable.

* `_defaults` and `_instanceof` are now reserved service names in Yaml configurations. Please rename any services with that names.
Expand Down Expand Up @@ -338,9 +382,9 @@ FrameworkBundle
class instead.

* Using the `KERNEL_DIR` environment variable and the automatic guessing based
on the `phpunit.xml` file location have been removed from the `KernelTestCase::getKernelClass()`
on the `phpunit.xml` file location have been removed from the `KernelTestCase::getKernelClass()`
method implementation. Set the `KERNEL_CLASS` environment variable to the
fully-qualified class name of your Kernel or override the `KernelTestCase::createKernel()`
fully-qualified class name of your Kernel or override the `KernelTestCase::createKernel()`
or `KernelTestCase::getKernelClass()` method instead.

* The `Symfony\Bundle\FrameworkBundle\Validator\ConstraintValidatorFactory` class has been removed.
Expand All @@ -349,10 +393,10 @@ FrameworkBundle
* The `--no-prefix` option of the `translation:update` command has
been removed.

* The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddCacheClearerPass` class has been removed.
* The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddCacheClearerPass` class has been removed.
Use the `Symfony\Component\HttpKernel\DependencyInjection\AddCacheClearerPass` class instead.

* The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddCacheWarmerPass` class has been removed.
* The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddCacheWarmerPass` class has been removed.
Use the `Symfony\Component\HttpKernel\DependencyInjection\AddCacheWarmerPass` class instead.

* The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslationDumperPass`
Expand Down Expand Up @@ -554,7 +598,7 @@ TwigBridge
* The `TwigRendererEngine::setEnvironment()` method has been removed.
Pass the Twig Environment as second argument of the constructor instead.

* Removed `Symfony\Bridge\Twig\Command\DebugCommand::set/getTwigEnvironment` and the ability
* Removed `Symfony\Bridge\Twig\Command\DebugCommand::set/getTwigEnvironment` and the ability
to pass a command name as first argument.

* Removed `Symfony\Bridge\Twig\Command\LintCommand::set/getTwigEnvironment` and the ability
Expand Down
1 change: 1 addition & 0 deletions src/Symfony/Component/DependencyInjection/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ CHANGELOG
3.4.0
-----

* deprecated autowiring service auto-registration
* deprecated the ability to check for the initialization of a private service with the `Container::initialized()` method
* deprecated support for top-level anonymous services in XML

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,8 @@ private function createAutowiredDefinition($type)
$this->currentId = $currentId;
}

@trigger_error(sprintf('Using autowiring service auto-registration for type "%s" is deprecated since version 3.4 and won\'t be supported in 4.0. Create a service named "%s" instead.', $type, $type), E_USER_DEPRECATED);

$this->container->log($this, sprintf('Type "%s" has been auto-registered for service "%s".', $type, $this->currentId));

return new TypedReference($argumentId, $type);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,11 @@ public function testWithTypeSet()
$this->assertEquals(CollisionInterface::class, (string) $container->getDefinition('a')->getArgument(0));
}

/**
* @group legacy
* @expectedDeprecation Using autowiring service auto-registration for type "Symfony\Component\DependencyInjection\Tests\Compiler\Lille" is deprecated since version 3.4 and won't be supported in 4.0. Create a service named "Symfony\Component\DependencyInjection\Tests\Compiler\Lille" instead.
* @expectedDeprecation Using autowiring service auto-registration for type "Symfony\Component\DependencyInjection\Tests\Compiler\Dunglas" is deprecated since version 3.4 and won't be supported in 4.0. Create a service named "Symfony\Component\DependencyInjection\Tests\Compiler\Dunglas" instead.
*/
public function testCreateDefinition()
{
$container = new ContainerBuilder();
Expand Down Expand Up @@ -368,6 +373,8 @@ public function testClassNotFoundThrowsException()
$aDefinition = $container->register('a', __NAMESPACE__.'\BadTypeHintedArgument');
$aDefinition->setAutowired(true);

$container->register(Dunglas::class, Dunglas::class);

$pass = new AutowirePass();
$pass->process($container);
}
Expand All @@ -383,6 +390,8 @@ public function testParentClassNotFoundThrowsException()
$aDefinition = $container->register('a', __NAMESPACE__.'\BadParentTypeHintedArgument');
$aDefinition->setAutowired(true);

$container->register(Dunglas::class, Dunglas::class);

$pass = new AutowirePass();
$pass->process($container);
}
Expand Down Expand Up @@ -595,6 +604,10 @@ public function testExplicitMethodInjection()
);
}

/**
* @group legacy
* @expectedDeprecation Using autowiring service auto-registration for type "Symfony\Component\DependencyInjection\Tests\Compiler\A" is deprecated since version 3.4 and won't be supported in 4.0. Create a service named "Symfony\Component\DependencyInjection\Tests\Compiler\A" instead.
*/
public function testTypedReference()
{
$container = new ContainerBuilder();
Expand Down Expand Up @@ -653,6 +666,8 @@ public function testIgnoreServiceWithClassNotExisting()
$barDefinition = $container->register('bar', __NAMESPACE__.'\Bar');
$barDefinition->setAutowired(true);

$container->register(Foo::class, Foo::class);

$pass = new AutowirePass();
$pass->process($container);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
use Symfony\Component\DependencyInjection\ServiceLocator;
use Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition;
use Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber;
use Symfony\Component\DependencyInjection\Variable;
use Symfony\Component\ExpressionLanguage\Expression;
Expand Down Expand Up @@ -560,6 +561,9 @@ public function testServiceSubscriber()
))
;
$container->register(TestServiceSubscriber::class, TestServiceSubscriber::class);

$container->register(CustomDefinition::class, CustomDefinition::class)
->setPublic(false);
$container->compile();

$dumper = new PhpDumper($container);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,16 @@ public function __construct()
{
$this->services = array();
$this->normalizedIds = array(
'autowired.symfony\\component\\dependencyinjection\\tests\\fixtures\\customdefinition' => 'autowired.Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CustomDefinition',
'symfony\\component\\dependencyinjection\\tests\\fixtures\\customdefinition' => 'Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CustomDefinition',
'symfony\\component\\dependencyinjection\\tests\\fixtures\\testservicesubscriber' => 'Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\TestServiceSubscriber',
);
$this->methodMap = array(
'Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CustomDefinition' => 'getSymfony_Component_DependencyInjection_Tests_Fixtures_CustomDefinitionService',
'Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\TestServiceSubscriber' => 'getSymfony_Component_DependencyInjection_Tests_Fixtures_TestServiceSubscriberService',
'autowired.Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CustomDefinition' => 'getAutowired_Symfony_Component_DependencyInjection_Tests_Fixtures_CustomDefinitionService',
'foo_service' => 'getFooServiceService',
);
$this->privates = array(
'autowired.Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CustomDefinition' => true,
'Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CustomDefinition' => true,
);

$this->aliases = array();
Expand Down Expand Up @@ -87,23 +87,23 @@ protected function getSymfony_Component_DependencyInjection_Tests_Fixtures_TestS
protected function getFooServiceService()
{
return $this->services['foo_service'] = new \Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber(new \Symfony\Component\DependencyInjection\ServiceLocator(array('Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CustomDefinition' => function () {
$f = function (\Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition $v) { return $v; }; return $f(${($_ = isset($this->services['autowired.Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition']) ? $this->services['autowired.Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition'] : $this->getAutowired_Symfony_Component_DependencyInjection_Tests_Fixtures_CustomDefinitionService()) && false ?: '_'});
$f = function (\Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition $v = null) { return $v; }; return $f(${($_ = isset($this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition']) ? $this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition'] : $this->getSymfony_Component_DependencyInjection_Tests_Fixtures_CustomDefinitionService()) && false ?: '_'});
}, 'Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\TestServiceSubscriber' => function () {
$f = function (\Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber $v) { return $v; }; return $f(${($_ = isset($this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber']) ? $this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber'] : $this->get('Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber')) && false ?: '_'});
}, 'bar' => function () {
$f = function (\Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition $v) { return $v; }; return $f(${($_ = isset($this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber']) ? $this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber'] : $this->get('Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber')) && false ?: '_'});
}, 'baz' => function () {
$f = function (\Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition $v) { return $v; }; return $f(${($_ = isset($this->services['autowired.Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition']) ? $this->services['autowired.Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition'] : $this->getAutowired_Symfony_Component_DependencyInjection_Tests_Fixtures_CustomDefinitionService()) && false ?: '_'});
$f = function (\Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition $v = null) { return $v; }; return $f(${($_ = isset($this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition']) ? $this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition'] : $this->getSymfony_Component_DependencyInjection_Tests_Fixtures_CustomDefinitionService()) && false ?: '_'});
})));
}

/**
* Gets the private 'autowired.Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition' shared autowired service.
* Gets the private 'Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition' shared service.
*
* @return \Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition
*/
protected function getAutowired_Symfony_Component_DependencyInjection_Tests_Fixtures_CustomDefinitionService()
protected function getSymfony_Component_DependencyInjection_Tests_Fixtures_CustomDefinitionService()
{
return $this->services['autowired.Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition'] = new \Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition();
return $this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition'] = new \Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition();
}
}