n1215/cake-candle

CakePHP3 兼容 PSR-11 的依赖注入插件

1.0.0 2020-04-22 12:42 UTC

This package is auto-updated.

Last update: 2024-09-22 23:03:53 UTC


README

一个兼容 PSR-11 的依赖注入插件,用于 CakePHP4。

Latest Stable Version License Build Status Code Coverage Scrutinizer Code Quality

要求

  • 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

使用方法

1. 安装你的 PSR-11 容器

例如,你可以使用 php-di/php-di。

composer require php-di/php-di

2. 修改你的 Application 类

<?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();

        // ...
    }

    // ...
}

3. 修改 bin/cake.php

// ...

+ 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());

4. 创建依赖

<?php
declare(strict_types=1);

namespace App;

class GreetingService
{
    public function hello(string $name): string
    {
        return "Hello, {$name}";
    }
}

5. 注入到控制器

辅助注入(方法注入)

扩展 AppController 并使用 N1215\CakeCandle\Http\AssistedAction trait。此 trait 可以在调用动作方法时填充类型声明的参数。

<?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;
    }
}

6. 注入到控制台命令

构造函数注入

按常规扩展 \Cake\Console\Command。类型声明的参数使用您的容器填充。

<?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));
    }
}

其他使用方法

@Inject 注释

你可以使用 @Inject 注释与 PHP-DI。

安装 doctrine/annotations。

composer require doctrine/annotations

在容器配置中启用注释。

// in Application::configureContainer();
$builder = new ContainerBuilder();
$builder->useAutowiring(true);
$builder->useAnnotations(true);

为控制器或命令属性添加 @Inject 和 @param 类型声明注释。

<?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));
    }
}

许可证

MIT 许可证(MIT)。请参阅 LICENSE 获取更多信息。