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.
推荐文章: