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("RedCrossQuest\Service\SlackService")
* @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 ?
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)
To workaround this, I manually did the job of PHP-DI.
// 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();