Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feature #34769 [DependencyInjection] Autowire public typed properties…
… (Plopix) This PR was merged into the 5.1-dev branch. Discussion ---------- [DependencyInjection] Autowire public typed properties | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | Deprecations? | no | License | MIT ### Description This PR adds the Autowiring of **public typed properties** in PHP 7.4. It is only on "public" properties. It could let people think that services are better injected in "public". I don't know what to think about it, you? ### How about "private" properties - further thinking Even if I think that it would be awesome to be able to inject in "private" properties, we discussed it with @nicolas-grekas, and I agree Symfony should not break any standard logic. If the property is private then it is private the DI cannot touch it. But that could/would remove a lot of boilerplate, and if it is declarative, that might still be something to do. Maybe we could introduce a new annotation for injection in "private": `@requiredPrivated` ? Commits ------- cad7fbb [DI] Autowire public typed properties
- Loading branch information
Showing
5 changed files
with
128 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,11 @@ | ||
CHANGELOG | ||
========= | ||
|
||
5.1.0 | ||
----- | ||
|
||
* added support to autowire public typed properties in php 7.4 | ||
|
||
5.0.0 | ||
----- | ||
|
||
|
61 changes: 61 additions & 0 deletions
61
src/Symfony/Component/DependencyInjection/Compiler/AutowireRequiredPropertiesPass.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of the Symfony package. | ||
* | ||
* (c) Fabien Potencier <fabien@symfony.com> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
namespace Symfony\Component\DependencyInjection\Compiler; | ||
|
||
use Symfony\Component\DependencyInjection\ContainerInterface; | ||
use Symfony\Component\DependencyInjection\Definition; | ||
use Symfony\Component\DependencyInjection\TypedReference; | ||
|
||
/** | ||
* Looks for definitions with autowiring enabled and registers their corresponding "@required" properties. | ||
* | ||
* @author Sebastien Morel (Plopix) <morel.seb@gmail.com> | ||
* @author Nicolas Grekas <p@tchwork.com> | ||
*/ | ||
class AutowireRequiredPropertiesPass extends AbstractRecursivePass | ||
{ | ||
/** | ||
* {@inheritdoc} | ||
*/ | ||
protected function processValue($value, bool $isRoot = false) | ||
{ | ||
if (\PHP_VERSION_ID < 70400) { | ||
return $value; | ||
} | ||
$value = parent::processValue($value, $isRoot); | ||
|
||
if (!$value instanceof Definition || !$value->isAutowired() || $value->isAbstract() || !$value->getClass()) { | ||
return $value; | ||
} | ||
if (!$reflectionClass = $this->container->getReflectionClass($value->getClass(), false)) { | ||
return $value; | ||
} | ||
|
||
$properties = $value->getProperties(); | ||
foreach ($reflectionClass->getProperties() as $reflectionProperty) { | ||
if (false === $doc = $reflectionProperty->getDocComment()) { | ||
continue; | ||
} | ||
if (false === stripos($doc, '@required') || !preg_match('#(?:^/\*\*|\n\s*+\*)\s*+@required(?:\s|\*/$)#i', $doc)) { | ||
continue; | ||
} | ||
if (\array_key_exists($name = $reflectionProperty->getName(), $properties)) { | ||
continue; | ||
} | ||
|
||
$type = $reflectionProperty->getType()->getName(); | ||
$value->setProperty($name, new TypedReference($type, $type, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, $name)); | ||
} | ||
|
||
return $value; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
46 changes: 46 additions & 0 deletions
46
...mfony/Component/DependencyInjection/Tests/Compiler/AutowireRequiredPropertiesPassTest.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of the Symfony package. | ||
* | ||
* (c) Fabien Potencier <fabien@symfony.com> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
namespace Symfony\Component\DependencyInjection\Tests\Compiler; | ||
|
||
use PHPUnit\Framework\TestCase; | ||
use Symfony\Component\DependencyInjection\Compiler\AutowireRequiredPropertiesPass; | ||
use Symfony\Component\DependencyInjection\Compiler\ResolveClassPass; | ||
use Symfony\Component\DependencyInjection\ContainerBuilder; | ||
|
||
require_once __DIR__.'/../Fixtures/includes/autowiring_classes.php'; | ||
|
||
if (\PHP_VERSION_ID >= 70400) { | ||
require_once __DIR__.'/../Fixtures/includes/autowiring_classes_74.php'; | ||
} | ||
|
||
/** | ||
* @requires PHP 7.4 | ||
*/ | ||
class AutowireRequiredPropertiesPassTest extends TestCase | ||
{ | ||
public function testInjection() | ||
{ | ||
$container = new ContainerBuilder(); | ||
$container->register(Bar::class); | ||
$container->register(A::class); | ||
$container->register(B::class); | ||
$container->register(PropertiesInjection::class)->setAutowired(true); | ||
|
||
(new ResolveClassPass())->process($container); | ||
(new AutowireRequiredPropertiesPass())->process($container); | ||
|
||
$properties = $container->getDefinition(PropertiesInjection::class)->getProperties(); | ||
|
||
$this->assertArrayHasKey('plop', $properties); | ||
$this->assertEquals(Bar::class, (string) $properties['plop']); | ||
} | ||
} |
15 changes: 15 additions & 0 deletions
15
src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/autowiring_classes_74.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
<?php | ||
|
||
namespace Symfony\Component\DependencyInjection\Tests\Compiler; | ||
|
||
class PropertiesInjection | ||
{ | ||
/** | ||
* @required | ||
*/ | ||
public Bar $plop; | ||
|
||
public function __construct(A $a) | ||
{ | ||
} | ||
} |