Playing a little bit with the new PHP 8 attributes (annotations) (https://stitcher.io/blog/attributes-in-php-8) I started to create my own ones.
Simple example:
namespace CisTools\Attribute;
use Attribute;
use CisTools\Exception\BadAttributeMetadataException;
/**
* For defining a description.
*/
#[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD | Attribute::TARGET_FUNCTION)]
class Description
{
/**
* @param string $description
* @throws BadAttributeMetadataException
*/
public function __construct(string $description)
{
if (strlen($description) < 10) {
throw new BadAttributeMetadataException("This is description is too short.");
}
}
}
Hoping that the following code would throw an BadAttributeMetadataException
unfortunately it finishes successfully:
use CisTools\Attribute\Description;
#[Description("quack")]
class Test {
public function __construct() {
echo "hello world";
}
}
new Test();
Is there away to validate the metadata passed for (custom) attributes? Most probably the attributes have to be instantiated automatically somehow.
Everything is possible - as of today I have implemented a working solution for this problem which can very well be used in libraries (just in case somebody needs that too):
function cis_shutdown_validate_attributes()
{
if(!defined('CIS_DISABLE_ATTRIBUTE_VALIDATION')) {
foreach(get_declared_classes() as $class) {
try {
$reflection = new ReflectionClass($class);
} catch (\Throwable $throwable) {
continue;
}
$attributes = $reflection->getAttributes();
foreach ($attributes as $attribute) {
$attribute->newInstance();
}
}
}
}
register_shutdown_function('cis_shutdown_validate_attributes');
(You may also autoload it: Composer/PSR - How to autoload functions?)