twithers / laravel-php-attributes
在您的 Laravel 应用程序中轻松使用 PHP 8 属性
Requires
- php: ^8.0
- illuminate/contracts: ^8.70|^9.0|^10.0
Requires (Dev)
- orchestra/testbench: ^6.0|^7.0|^8.0
- phpunit/phpunit: ^9.3|^10.0
README
此包可以帮助您在 Laravel 应用程序中创建和使用自己的 PHP 8 属性,而无需担心编写自己的加载器、反射方法和数据缓存。
默认情况下,您的 app
目录中的所有属性都会自动加载和缓存,并提供访问器以在需要时查找属性。可以配置此包以限制目录以及属性,以提高加载速度并最小化缓存。
安装
使用以下命令使用 composer 安装此包
composer require twithers/laravel-php-attributes
您可以使用以下命令发布配置文件
php artisan vendor:publish --provider="TWithers\LaravelAttributes\AttributesServiceProvider" --tag="config"
这是已发布的配置文件的内容
return [ /** * Caching will make use of Laravel's built-in file caching. Using caching will be a massive performance benefit * as no directories and files need to be scanned for attributes and attribute usages */ 'use_cache' => true, /** * By default this will scan your listed directories below for all attributes and then search for them. * * If you want to avoid the initial search, you can list your attribute classes below: * 'App\Attributes\Foo', * App\Attributes\Bar::class, * */ 'attributes' => [ ], /** * By default this will scan all files inside your app folder for attributes. * * If you want to limit the folders, you can adjust the namespace and the files: * 'App\Http\Controllers' => app_path('Http/Controllers') */ 'directories' => [ 'App' => app_path(), ], ];
您可以禁用缓存,但不太推荐,因为每个请求都会扫描和建立属性集合。
您可以通过声明来限制属性列表。空数组表示将扫描列表中目录中找到的所有属性。
您可以缩小目录搜索范围,或列出多个单独的目录以查找属性及其使用情况。确保您的数组以 $namespace => $directoryPath
的结构来确保正确找到和访问文件。
PHP 8 中的属性
首先定义属性并命名空间。然后将 Attribute
属性应用于它。定义属性后,我们可以将其添加到任何我们想要的地方:类、方法、函数、属性等。以下是如何定义和使用属性的一个示例。
#[Attribute] class SampleAttribute { public string $name; public string $label; public function __construct( string $name, string $label ){ $this->name = name; $this->label = label; } } #[SampleAttribute(name: 'SampleClass', label: 'My Sample Class Label')] class SampleClass { #[SampleMethod(name: 'sampleMethod', label: 'My Sample Method Label')] public function sampleMethod(): bool { return true; } }
我们有一个已定义的属性 SampleAttribute
,它需要一个 name
和一个 label
。我们有一个使用该属性的 SampleClass
,以及使用该属性的方法 sampleMethod()
。
在 PHP 8+ 中查找属性
属性本身没有任何作用。PHP 目前没有提供一种超级简单的方式来捕获属性和值。您将被迫使用 PHP 反射,这可能不是您曾经使用过的。反射就是反射代码。您传递一些信息,例如类名、方法名等,Reflection API 将提供您需要了解的所有信息...包括属性。
以下是您当前如何使用反射 API 来查找属性的方法。
$reflectionClass = new ReflectionClass(SampleClass::class); $attributes = $reflectionClass->getAttributes(SampleMethod::class); if (count($attributes)){ $attribute = $attributes[0]->newInstance(); dump($attribute->name); // "SampleClass" dump($attribute->label); // "My Sample Class Label" } $reflectionClass = new ReflectionClass(SampleClass::class); $reflectionMethod = $reflectionClass->getMethod('sampleMethod'); $attributes = $reflectionMethod->getAttributes(SampleMethod::class); if (count($attributes)){ $attribute = $attributes[0]->newInstance(); dump($attribute->name); // "Sample Method" dump($attribute->label); // "My Sample Method" }
这段代码不多,但很容易理解。但是,如果您在应用程序中广泛使用属性,您很快就会发现自己重复这段代码。
进入 Laravel PHP Attributes
使用
访问 AttributeCollection API
此包提供了 Attributes
门面,帮助您在处理之后访问存储的属性集合数据。您还可以在应用程序中为 AttributeCollection
类提供类型提示,Laravel 将自动加载初始化的属性集合。
Attributes
门面和 AttributeCollection
提供以下有用的方法
Attributes::findByClass(string $className): ?AttributeTarget Attributes::findByClassMethod(string $className, string $methodName): ?AttributeTarget Attributes::findByClassProperty(string $className, string $propertyName): ?AttributeTarget Attributes::findTargetsWithAttribute(string $attributeName): AttributeTarget[]
AttributeTarget
是属性附加到的类、方法或属性。AttributeTarget
具有以下结构
- int $type:指示目标是否为类、方法或属性
- 字符串 $className:被目标或包含属性的类的完整命名空间名称
- ?string $identifier:方法或属性的名称
- allAttributes(): AttributeInstance[]:获取所有附加属性列表的方法(包括
$name
和实例化的$instance
)
以下是上述代码的修改方式
$attributes = Attributes::findByClass(SampleClass::class)->allAttributes(); dump($attributes[0]->instance->name); // "SampleClass" dump($attributes[0]->instance->label); // "My Sample Class Label" $attributes = Attributes::findByClassMethod(SampleClass::class, 'sampleMethod')->allAttributes(); dump($attributes[0]->instance->name); // "Sample Method" dump($attributes[0]->instance->label); // "My Sample Method"
AttributeTarget API
AttributeTarget
类还公开了一些有用的方法,用于查找特定属性
AttributeTarget::allAttributes(): AttributeInstance[] AttributeTarget::hasAttribute(string $attributeName): bool AttributeTarget::findByName(string $attributeName): AttributeInstance[]
独立使用
如果您不想使用 Laravel 服务提供器的自动加载和缓存属性,您可以从加载的服务提供程序列表中删除它。如果您知道相关信息,可以使用 AttributeAccessor
类来查找属性。以下是可以使用的方法
AttributeAccessor::forClass(string $className): ?AttributeInstance[] AttributeAccessor::forClassMethod(string $className, string $methodName): ?AttributeInstance[] AttributeAccessor::forClassProperty(string $className, string $propertyName): ?AttributeInstance[]
如果找不到类、方法或属性,它将返回 null
,否则,每个静态函数都会查找所有附加属性,并返回一个包含具有 $name
和 $instance
属性的 AttributeInstances
数组的数组供您使用。
清除属性缓存
默认情况下,属性将在首次请求时查找和处理,并将结果缓存起来。后续请求将使用缓存数据来避免昂贵的处理时间。这意味着对属性或使用属性的更改将需要清除缓存。默认情况下(除非您的环境设置为将文件存储在不同的位置),缓存文件存储在 bootstrap\cache\attributes.php
中,可以手动删除。您还可以使用以下命令
php artisan attributes:clear
在部署过程中使用此命令将确保添加的属性被正确缓存。
测试
./vendor/bin/phpunit
贡献
欢迎所有贡献。
谢谢!
由 contrib.rocks 制作。
许可证
MIT 许可证(MIT)。有关更多信息,请参阅 许可证文件