Attribute usage in top-1000 PHP packages

Attributes were originally introduced in PHP 8.0 two years ago. Yesterday, I came across an interesting post from Exakat: they analysed 535 open source packages to see which attributes were used the most often.

However: they didn't share their raw data or absolute numbers, and they also didn't mention which packages were analysed exactly and how.

I think we can do better. So let's take a closer look at how attributes are used in the PHP open source community.

# Setup

I used Nikita's Popular Package Analyser: it downloads the top-1000 packages from Packagist, and allows you to run analysis on them by writing simple PHP scripts.

In this case I looped over all PHP files, and scanned whether they contained attributes. You can check out the full script here.

A couple of remarks:

The first metric that stood out is that #[\ReturnTypeWillChange] outnumbers all others by far: out of 2786 attributes in total, 1668 are either #[\ReturnTypeWillChange] or #[ReturnTypeWillChange], that's almost 60% being ReturnTypeWillChange attributes.

This attribute is the first built-in attribute in PHP, introduced in PHP 8.1, and meant to deal with a newly added deprecation notice. It was a design goal of the original attribute RFC to use them for these kinds of cases where we want userland code to communicate information to PHP's interpreter. In this case: to suppress a deprecation notice.

Speaking of the two variants (with and without a leading \): some developers import their attributes and others use the fully qualified class name: the latter option is by far the preferred one: out of 1668 ReturnTypeWillChange usages, only 524 imported the attribute — that's only 31%. It seems that most developers like to use the FQCN variant.

# The most active packages

Out of 997 packages, only 200 packages are using attributes. Out of those 200, Symfony, Drupal and Laravel have large pieces of the pie. Symfony is the leader here with 9.6%: not unlikely caused by the fact that Symfony has been using docblock annotations for years.

# Custom attributes

Another point of interest is the use of #[Attribute] and #[\Attribute]: representing custom attributes provided by packages themselves. In total there are 561 custom attributes provided by these packages.

Looking on a per-package basis: Symfony provides 88 custom attributes, with PHPUnit providing 49, and doctrine's mongodb implementation providing 42. Again a clear example of how Symfony is an early adopter, thanks to them being used to docblock annotations for years. Interestingly, Laravel provides no custom attributes.

# Multiline attributes

It's remarkable that there are no vendors using multiline attributes:

#[
    AsCommand,
    ReturnTypeWillChange,
]

It makes sense that vendors opt for the single-line notation, since it's compatible with older PHP versions because these lines are treated like comments before PHP 8.0:

#[AsCommand]
#[ReturnTypeWillChange]

# Conclusions

On a personal note: I'd say there's room for improvement. I think Laravel should start embracing custom attributes, especially since they now require PHP 8.0 as their minimum version.

What's your opinion? Let me know via Twitter or email!

Noticed a tpyo? You can submit a PR to fix it. If you want to stay up to date about what's happening on this blog, you can subscribe to my mailing list: send an email to brendt@stitcher.io, and I'll add you to the list.