I’m using Slim 4.5.0 with PHP-DI 6 and I’ve a circular dependency issue.
I know how to solve this kind of issue using a setter, but in the context of SlimFramework, I can’t get anything to work.
I want to send message to a Slack Channel when an error occurs.
LoggerInterface::class => function (ContainerInterface $c):Logger { return new Logger($c->get(SlackService::class), $c->get("googleLogger"), (string)$c->get("RCQVersion"), $c->get('settings')['appSettings']['deploymentType'], $c->get('settings')['online']); }, SecretManagerService::class => function (ContainerInterface $c):SecretManagerService { return new SecretManagerService($c->get('settings'), $c->get(LoggerInterface::class)); }, SlackService::class =>function(ContainerInterface $c):SlackService { $slackToken = $c->get(SecretManagerService::class)->getSecret(SecretManagerService::$SLACK_TOKEN); return new SlackService($slackToken, (string)$c->get("RCQVersion"), $c->get('settings')['appSettings']['deploymentType'], $c->get('settings')['online']); },
What I need is to provide the SlackService to the my custom Logger.
I’ve tried to use @Inject keyword in my Logger class to set the Slack Service (and remove it from the constructor):
/** * @Inject * @var SlackService $slackService */ private $slackService;
Or use a setter function and @Inject (with and without the class Name)
/** * @Inject("RedCrossQuestServiceSlackService") * @param SlackService $slackService */ public function setSlackService(SlackService $slackService) { $this->slackService = $slackService; }
But this doesn’t work, while I feel it’s the way to go.
I already use @Inject to set property on my class (string value), and it works well, but here, for some reasons it doesn’t.
I didn’t find here anything that could help to understand why it wouldn’t work. https://php-di.org/doc/annotations.html
Each time an error occurs, I get an error saying slackService is null
Uncaught Error: Call to a member function postMessage() on null
What am I missing to make the @Inject() work ?
Advertisement
Answer
As pointed by Nima with the tickets, Circular Dependencies can’t be solved using setter, unless you use Lazy Loading. The catch is that it requires a proxy libs, that have 3 additional dependencies, which is a bit overkill for my simple use case. (also it seems that there’s a missing step in the documentation of PHP-DI)
- zendframework/zend-eventmanager (3.2.1)
- zendframework/zend-code (3.4.1)
- ocramius/proxy-manager (2.2.3)
- ocramius/package-versions (1.5.1)
To workaround this, I manually did the job of PHP-DI.
- I set a setter on my Logger to set the SlackService, once the container is built, and I did not add the @Inject in the comments above the setter method.
// Set up dependencies $dependencies = require __DIR__ . '/../../src/dependencies.php'; $dependencies($containerBuilder); // Build PHP-DI Container instance $container = $containerBuilder->build(); $loggerInterface = $container->get(LoggerInterface::class); $loggerInterface->setSlackService ($container->get(SlackService::class); // Instantiate the app AppFactory::setContainer($container); $app = AppFactory::create();