Skip to content
Advertisement

PHP 8 Attributes: Is it possible to validate metadata passed to attributes or force attribute instantiation?

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 CisToolsAttribute;

use Attribute;
use CisToolsExceptionBadAttributeMetadataException;

/**
 * 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 CisToolsAttributeDescription;

#[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.

Advertisement

Answer

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

User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement