Motivation
I want to inject Service to Command and Controller by DI container.
In addition, Service uses Repository injected.
The document doesn't mention this case like nested injection.
Document
https://book.cakephp.org/4/en/development/dependency-injection.html
How to implement
Service and Repository
interface SomeRepository {
public getAll(): array;
}
class SomeRepositoryImpl implements SomeRepository
{
public function getAll(): array
{
print('getAll()');
return [];
}
}
class SomeService
{
private $someRepository;
public function __construct(SomeRepository $someRepository)
{
$this->someRepository = $someRepository;
}
public function doSomething(): void
{
$this->someRepository->getAll();
}
}
Comamnd
use Cake\Command\Command;
use Cake\Console\Arguments;
use Cake\Console\ConsoleIo;
use Cake\Console\ConsoleOptionParser;
class SomeCommand extends Command
{
private SomeService $service;
public function __construct(SomeService $service)
{
parent::__construct();
$this->service = $service;
}
public static function getDescription(): string
{
return 'Inject service through provider';
}
public function buildOptionParser(ConsoleOptionParser $parser): ConsoleOptionParser
{
$parser = parent::buildOptionParser($parser);
return $parser;
}
public function execute(Arguments $args, ConsoleIo $io)
{
$this->service->doSomething();
}
}
use Cake\Core\ContainerInterface;
use Cake\Core\ServiceProvider;
class CommandServiceProvider extends ServiceProvider
{
protected $provides = [
SomeCommand::class,
];
public function services(ContainerInterface $container): void
{
$container
->add(SomeCommand::class)
->addArgument(SomeService::class);
}
}
Controller
use Cake\Controller\Controller;
class SomeController extends Controller
{
public function index(SomeService $service)
{
$service->doSomething();
print('index()');
}
}
Register to DI container
use Cake\Core\ContainerInterface;
use Cake\Core\ServiceProvider;
class SomeServiceProvider extends ServiceProvider
{
protected $provides = [
SomeService::class,
];
public function services(ContainerInterface $container): void
{
$container
->add(SomeRepository::class, SomeRepositoryImpl::class);
$container
->add(SomeService::class)
->addArgument(SomeRepository::class);
}
}
// Application.php
class Application extends BaseApplication
{
// ...
public function services(ContainerInterface $container): void
{
$container->addServiceProvider(new SomeServiceProvider());
$container->addServiceProvider(new ControllerServiceProvider());
}
// ...
Top comments (0)