laravel 中实现注解注入 | laravel china 社区-江南app体育官方入口

创建注解类


declare(strict_types=1);
namespace app\support\attributes;
#[\attribute(\attribute::target_property)]
readonly class injection
{
    public function __construct(
        public ?string $propertytype = null,
        public array $parameters = []
    ) {}
}

引导解析注解


declare(strict_types=1);
namespace app\providers;
use app\support\attributes\injection;
use illuminate\foundation\application;
use illuminate\support\serviceprovider;
class appserviceprovider extends serviceprovider
{
    public function register(): void {}
    public function boot(): void
    {
        $this->injection();
    }
    private function injection(): void
    {
        $this->app->resolving(static function (mixed $object, application $app): void {
            if (! \is_object($object)) {
                return;
            }
            $class = str($object::class);
            if (
                ! $class->is(config('services.injection.only'))
                || $class->is(config('services.injection.except'))
            ) {
                return;
            }
            $reflectionobject = new \reflectionobject($object);
            foreach ($reflectionobject->getproperties() as $reflectionproperty) {
                if (! $reflectionproperty->isdefault() || $reflectionproperty->isstatic()) {
                    continue;
                }
                $attributes = $reflectionproperty->getattributes(injection::class);
                if ($attributes === []) {
                    continue;
                }
                /** @var injection $injection */
                $injection = $attributes[0]->newinstance();
                $propertytype = value(static function () use ($injection, $reflectionproperty, $reflectionobject): string {
                    if ($injection->propertytype) {
                        return $injection->propertytype;
                    }
                    $reflectionpropertytype = $reflectionproperty->gettype();
                    if ($reflectionpropertytype instanceof \reflectionnamedtype && ! $reflectionpropertytype->isbuiltin()) {
                        return $reflectionpropertytype->getname();
                    }
                    throw new \logicexception(\sprintf(
                        'attribute [%s] of %s miss a argument, or %s must be a non-built-in named type.',
                        injection::class,
                        $property = "property [{$reflectionobject->getname()}::\${$reflectionproperty->getname()}]",
                        $property,
                    ));
                });
                $reflectionproperty->ispublic() or $reflectionproperty->setaccessible(true);
                $reflectionproperty->setvalue($object, $app->make($propertytype, $injection->parameters));
            }
        });
    }
}

配置解析范围(可选)

config/services.php


return [
    // ...
    'injection' => [
        'only' => [
            'app\*',
        ],
        'except' => [
            'app\support\macros\*',
        ],
    ],
];

使用

示例


declare(strict_types=1);
namespace app\console\commands;
use app\support\attributes\injection;
use app\support\hmacsigner;
use illuminate\config\repository;
class testcommand extends \illuminate\console\command
{
    protected $signature = 'test';
    #[injection('path.storage')]
    private string $storagepath;
    #[injection(parameters: ['secret' => 'secret...'])]
    private hmacsigner $hmacsigner;
    #[injection(repository::class)]
    private repository $repositoryofinjectionpropertytype;
    #[injection('config')]
    private repository $repositoryofinjectioninstancekey;
    #[injection]
    private repository $repositoryofreflectionpropertytype;
    public function handle(): void
    {
        dump(
            $this->storagepath,
            $this->hmacsigner,
            $this->repositoryofinjectionpropertytype->get('services.injection'),
            $this->repositoryofinjectioninstancekey->get('services.injection.only'),
            $this->repositoryofreflectionpropertytype->get('services.injection.except'),
        );
    }
}

输出

╰─ ./artisan test                                                                                ─╯
"/users/yaozm/documents/wwwroot/laravel-skeleton/storage" // app/console/commands/testcommand.php:32
app\support\hmacsigner {#2045
  -secret: "secret..."
  -algo: "sha256"
} // app/console/commands/testcommand.php:32
array:2 [
  "only" => array:1 [
    0 => "app\*"
  ]
  "except" => array:1 [
    0 => "app\support\macros\*"
  ]
] // app/console/commands/testcommand.php:32
array:1 [
  0 => "app\*"
] // app/console/commands/testcommand.php:32
array:1 [
  0 => "app\support\macros\*"
] // app/console/commands/testcommand.php:32

与依赖注入比较

功能 注解注入 依赖注入
标量类型 已支持 未支持
传参 已支持 未支持

相关连接

原文连接

本作品采用《cc 协议》,转载必须注明作者和本文链接
no practice, no gain in one's wit.
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
以构建论坛项目 larabbs 为线索,展开对 laravel 框架的全面学习。应用程序架构思路贴近 laravel 框架的设计哲学。
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!
未填写
文章
57
粉丝
128
喜欢
980
收藏
1342
排名:45
访问:15.4 万
博客标签
社区赞助商
网站地图