Closed
Description
Q | A |
---|---|
Bug report? | no |
Feature request? | yes |
BC Break report? | no |
RFC? | yes |
Symfony version | 3.4 |
Here's a proposal coming mostly from @nicolas-grekas (I helped a bit making the example :)).
Would you like to be able use a class factory to define your services?
Main benefits:
- service names based on the methods return type (or
@Alias
) - arguments injection based on autowiring
- access to php functions at runtime (no need anymore of the expression language), that also means access to
getenv()
- possibility to manually inline simple services
An example of how it could be used:
// services.yaml
imports:
- type: service_factory
resource: App\MyServicesFactory
// src/MyServicesFactory.php
<?php
namespace App;
use App\Entity\Product;
use Doctrine\Bundle\DoctrineBundle\Registry;
use Psr\Logger\LoggerInterface;
class MyServicesFactory
{
private static $apiKey = 'foo';
private $database;
public function __construct()
{
// Constructor called with *no* argument
}
/**
* @Tag(name="monolog.logger", channel="my_channel")
* @Alias(id="my_service")
* @Alias // when used with no id, the return type is used
* @Param("strategies", tag="app.strategies")
*
* @param StrategyInterface[] $strategies // it's the responsibility of a DI extension to populate this
*/
public function myService(LoggerInterface $logger, iterable $strategies): MyServiceInterface
{
$myService = new MyService($logger);
$myService->setSecret(self::$apiKey); // the service can be easily configured
$myService->setSecret(getenv('API_KEY')); // even dynamically
foreach ($strategies as $strategy) {
$myService->addStrategy();
}
// Less flexible than an injected dep, but still a nice shortcut for private apps
// benefits from type hinting (return type vs argument type can be verified by IDEs)
$myService->setDatabase($this->myDatabase());
return $myService;
}
/**
* ExpressionLanguage not needed anymore.
*/
public function myController(MyService $myService, Repository $doctrine): MyController
{
return new MyController($myService, $doctrine->getRepository(Product::class));
}
protected function myDatabase(): DatabaseInterface
{
return $this->database ?? $this->database = new Database('dns://...');
}
}
Wdyt? This could be an alternative to #22407.
<
56A0
div>