I was looking for a convenient way to retrieve targets of PHP 8 attributes, so I could use them in my packages. I couldn't find any, so I wrote one that comes in the form of a Composer plugin.
composer-attribute-collector provides a zero-configuration, near zero-cost system to retrieve targets of PHP 8 attributes. In order to do that, after the autoloader has been dumped, the plugin collects attribute targets and generates a static file. Later, these targets can be retrieved through a convenient interface.
Featured on PHP Annotated – January 2023
For example, with a Symfony application, the plugin would generate something like this excerpt:
<?php
// attributes.php @generated by https://github.com/olvlvl/composer-attribute-collector
namespace olvlvl\ComposerAttributeCollector;
Attributes::with(fn () => new Collection(
targetClasses: [
\Symfony\Component\Console\Attribute\AsCommand::class => [
[ ['lint:yaml', 'Lint a YAML file and outputs encountered errors'], \Symfony\Component\Yaml\Command\LintCommand::class ],
[ ['server:dump', 'Start a dump server that collects and displays dumps in a single place'], \Symfony\Component\VarDumper\Command\ServerDumpCommand::class ],
[ ['debug:validator', 'Display validation constraints for classes'], \Symfony\Component\Validator\Command\DebugCommand::class ],
[ ['translation:pull', 'Pull translations from a given provider.'], \Symfony\Component\Translation\Command\TranslationPullCommand::class ],
The following example demonstrates how targets and their attributes can be retrieved:
<?php
use olvlvl\ComposerAttributeCollector\Attributes;
use Symfony\Component\Messenger\Attribute\AsMessageHandler;
use Symfony\Component\Routing\Annotation\Route;
require_once 'vendor/autoload.php';
require_once 'vendor/attributes.php'; // <-- the file created by the plugin
// Find the target classes of the AsMessageHandler attribute.
foreach (Attributes::findTargetClasses(AsMessageHandler::class) as $target) {
// $target->attribute is an instance of the specified attribute
// with the actual data.
var_dump($target->name, $target->attribute);
}
// Find the target methods of the Route attribute.
foreach (Attributes::findTargetMethods(Route::class) as $target) {
var_dump($target->class, $target->name, $target->attribute);
}
// Find attributes for the ArticleController class.
$attributes = Attributes::forClass(ArticleController::class);
var_dump($attributes->classAttributes);
var_dump($attributes->methodsAttributes);
If that looks helpful to you, checkout composer-attribute-collector on GitHub.