A PSR-11 compatible dependency injection plugin for CakePHP4.
- CakePHP >= 4.0
# Create your CakePHP4 project.
composer create-project --prefer-dist cakephp/app your_app
cd your_app
# Install CakeCandle.
composer require n1215/cake-candle
You can use php-di/php-di for example.
composer require php-di/php-di
<?php
declare(strict_types=1);
namespace App;
// ...
use Cake\Http\BaseApplication;
// ...
use DI\ContainerBuilder;
use N1215\CakeCandle\ContainerBagLocator;
use N1215\CakeCandle\Controller\ControllerFactory;
// ...
class Application extends BaseApplication
{
// 1. configure a PSR-11 compatible container as you like.
private function configureContainer()
{
$builder = new ContainerBuilder();
$builder->useAutowiring(true);
$builder->useAnnotations(false);
return $builder->build();
}
// 2. initialize ContainerBagLocator and ControllerFactory with the configured container in Application::bootstrap().
public function bootstrap(): void
{
try {
$container = $this->configureContainer();
ContainerBagLocator::init($container);
$this->controllerFactory = new ControllerFactory(ContainerBagLocator::get());
} catch (\Exception $e) {
throw new \RuntimeException('Failed to configure the di container.', 0, $e);
}
// Call parent to load bootstrap from files.
parent::bootstrap();
// ...
}
// ...
}
// ...
+ use N1215\CakeCandle\Console\CommandFactory;
// add CommandFactory to CommandRunner constructor parameters.
- $runner = new CommandRunner(new Application(dirname(__DIR__) . '/config'), 'cake');
+ $runner = new CommandRunner(new Application(dirname(__DIR__) . '/config'), 'cake', new CommandFactory());
<?php
declare(strict_types=1);
namespace App;
class GreetingService
{
public function hello(string $name): string
{
return "Hello, {$name}";
}
}
Extends AppController and use N1215\CakeCandle\Http\AssistedAction trait. This trait can fill type declared parameters when action methods are invoked.
<?php
declare(strict_types=1);
namespace App\Controller;
use App\GreetingService;
use Cake\Http\Response;
class HelloController extends AppController
{
public function index(string $name, GreetingService $greetingService): Response
{
$suffix = $this->request->getQuery('suffix', 'san');
$this->response
->getBody()
->write($greetingService->hello($name . ' ' . $suffix));
return $this->response;
}
}
Extends \Cake\Console\Command as usual. Type declared parameters are filled using your container.
<?php
declare(strict_types=1);
namespace App\Command;
use App\GreetingService;
use Cake\Console\Arguments;
use Cake\Console\Command;
use Cake\Console\ConsoleIo;
use Cake\Console\ConsoleOptionParser;
class HelloCommand extends Command
{
/**
* @var GreetingService
*/
private $greetingService;
public function __construct(GreetingService $greetingService)
{
parent::__construct();
$this->greetingService = $greetingService;
}
protected function buildOptionParser(ConsoleOptionParser $parser): ConsoleOptionParser
{
$parser->addArgument('name', [
'help' => 'name'
]);
return $parser;
}
public function execute(Arguments $args, ConsoleIo $io): void
{
$name = $args->getArgument('name');
$io->out($this->greetingService->hello($name));
}
}
You can use @Inject annotation with PHP-DI.
Install doctrine/annotations.
composer require doctrine/annotations
Enable annotations on your container configuration.
// in Application::configureContainer();
$builder = new ContainerBuilder();
$builder->useAutowiring(true);
$builder->useAnnotations(true);
Add @Inject and @param Type declaration comments for your controller or command properties.
<?php
declare(strict_types=1);
namespace App\Controller;
use App\GreetingService;
use Cake\Http\Response;
class HelloController extends AppController
{
/**
* @Inject
* @var GreetingService
*/
private $greetingService;
public function index(string $name): Response
{
$suffix = $this->request->getQuery('suffix', 'san');
$this->response
->getBody()
->write($this->greetingService->hello($name . ' ' . $suffix));
return $this->response;
}
}
<?php
declare(strict_types=1);
namespace App\Command;
use App\GreetingService;
use Cake\Console\Arguments;
use Cake\Console\Command;
use Cake\Console\ConsoleIo;
use Cake\Console\ConsoleOptionParser;
class HelloCommand extends Command
{
/**
* @Inject
* @var GreetingService
*/
private $greetingService;
protected function buildOptionParser(ConsoleOptionParser $parser): ConsoleOptionParser
{
$parser->addArgument('name', [
'help' => 'name'
]);
return $parser;
}
public function execute(Arguments $args, ConsoleIo $io): void
{
$name = $args->getArgument('name');
$io->out($this->greetingService->hello($name));
}
}
The MIT License (MIT). Please see LICENSE for more information.