Plugin attributes and hooks
Drupal 11 declares plugins with PHP attributes. You put the attribute on a class in the matching src/Plugin/... directory, and the plugin manager discovers it. Annotations (the @Block-style docblocks) are the legacy form, still supported but no longer written for new code. The plugins concept page explains the system; this page is the lookup.
Example
Section titled “Example”namespace Drupal\event_rsvp\Plugin\Block;
use Drupal\Core\Block\Attribute\Block;use Drupal\Core\Block\BlockBase;use Drupal\Core\StringTranslation\TranslatableMarkup;
#[Block( id: 'event_rsvp_count', admin_label: new TranslatableMarkup('RSVP count'),)]final class RsvpCountBlock extends BlockBase { // ...}Common plugin attributes
Section titled “Common plugin attributes”| Attribute | Declares | Plugin directory |
|---|---|---|
\Drupal\Core\Block\Attribute\Block | A block | src/Plugin/Block |
\Drupal\Core\Field\Attribute\FieldType | A field type | src/Plugin/Field/FieldType |
\Drupal\Core\Field\Attribute\FieldWidget | A field widget | src/Plugin/Field/FieldWidget |
\Drupal\Core\Field\Attribute\FieldFormatter | A field formatter | src/Plugin/Field/FieldFormatter |
\Drupal\Core\Action\Attribute\Action | An action | src/Plugin/Action |
\Drupal\Core\Condition\Attribute\Condition | A condition | src/Plugin/Condition |
\Drupal\Core\Queue\Attribute\QueueWorker | A queue worker | src/Plugin/QueueWorker |
\Drupal\Core\Layout\Attribute\Layout | A layout | src/Plugin/Layout |
\Drupal\Core\Mail\Attribute\Mail | A mail backend | src/Plugin/Mail |
\Drupal\Core\Validation\Attribute\Constraint | A validation constraint | src/Plugin/Validation/Constraint |
Entity types are declared the same way, with \Drupal\Core\Entity\Attribute\ContentEntityType or ConfigEntityType on the entity class. Custom entity types covers them.
Views handlers each have an attribute under \Drupal\views\Attribute\ (ViewsField, ViewsFilter, ViewsArgument, ViewsStyle, and the rest), one per handler type, in the matching src/Plugin/views/<type> directory.
Annotations (legacy)
Section titled “Annotations (legacy)”Every attribute above has an annotation predecessor in an Annotation namespace (for example \Drupal\Core\Block\Annotation\Block). You will meet them in older contrib, but each annotated plugin triggers a deprecation notice, and annotation discovery is removed in Drupal 13. Write attributes for new code, and convert annotations when you touch a file. The @Translation annotation wrapper has no attribute equivalent: in attributes, pass new TranslatableMarkup('...') directly.
OOP hooks
Section titled “OOP hooks”Hooks are implemented as methods marked with the Hook attribute, instead of procedural hook_*() functions. Hooks and events explains how to write them; convert procedural hooks to classes covers migrating existing code.
| Attribute | Purpose |
|---|---|
\Drupal\Core\Hook\Attribute\Hook | Marks a method as a hook implementation: #[Hook('form_alter')]. |
\Drupal\Core\Hook\Attribute\RemoveHook | Removes another module’s hook implementation. |
\Drupal\Core\Hook\Attribute\ReorderHook | Reorders another module’s hook implementation. |
\Drupal\Core\Hook\Attribute\LegacyHook | Marks a procedural stub that Drupal 11.1 and later skip because a class implementation exists. |
\Drupal\Core\Hook\Attribute\LegacyModuleImplementsAlter | Marks a hook_module_implements_alter() that Drupal 11.2 and later skip in favor of attribute ordering. |
\Drupal\Core\Hook\Attribute\ProceduralHookScanStop | Placed on a function in a .module file; Drupal stops scanning the file for procedural hooks after that function. |
Order an implementation with the order argument:
| Value | Effect |
|---|---|
\Drupal\Core\Hook\Order\Order::First / Order::Last | Run before or after all others. |
\Drupal\Core\Hook\Order\OrderBefore / OrderAfter | Run relative to a named module’s implementation. |
Related
Section titled “Related”- Plugins for how discovery and managers work.
- Hooks and events for implementing hooks as methods.
- Convert procedural hooks to classes for migrating existing code.
- The
plugin API topicon api.drupal.org.
Was this page helpful?
Drupal is a registered trademark of Dries Buytaert.