In my Slim v4, application, I am setting up the container definitions as below.
$containerBuilder = new ContainerBuilder();
$containerBuilder->useAttributes(true);
$containerBuilder->addDefinitions([
MailerInterface::class => function (ContainerInterface $container) {
$dsn = sprintf(
'%s://%s:%s@%s:%s',
"smtp",
"username",
"password",
"hostname",
"587"
);
return new Mailer(Transport::fromDsn($dsn));
}
]);
I can use the MailerInterface in my controllers without any issue.
<?php
abstract class BaseController
{
protected MailerInterface $mailer;
/* DI works in constructor as part of the controller */
public function __construct(MailerInterface $mailer)
{
$this->mailer = $mailer;
}
}
This works perfectly fine as part of the controller. But I am looking for creating a service which can be used anywhere in the application and not only in the controllers.
My intended usage of the service class is as follows. I don't want my users to deal with dependencies creation and hence the empty constructor.
$m = new MailerService();
$m->sendEmail(($email));
My service class is as below as I am trying to inject the dependency as per doc in https://php-di.org/doc/attributes.html.
final class MailerService
{
private MailerInterface $mailer;
public function __construct(#[Inject('MailerInterface')] MailerInterface $mailer)
{
$this->mailer = $mailer;
}
public function sendEmail(Email $email): void
{
$this->mailer->send($email);
}
}
What is missing in my implementation? Any help is appreciated.
Dependency injection containers don't change how normal PHP code works; if you write
new MailerService();that still means "run the constructor with no arguments".What dependency injection containers do is define how to create an instance when you ask for one from the container. (Generally, they also return the same instance each time you ask for one, rather than repeating the constructor call.)
In other words, when you write this:
Then the container runs this:
So what you need to do is replace code using the
newoperator. That means either: