Plugins are one of the ways that module developers can write code that extends Drupal. The Drupal Plugin API allows a module to provide functionality in an extensible, object-oriented way. Plugins are used to solve the problem where you need to allow one or more modules to provide additional "things" that implement the same interface but provide distinctly different functionality. In most cases, you also want to provide a site administrator with a list of those "things" so she can choose and configure the appropriate functionality for her use case.
Plugins are grouped into plugin types which are managed by a plugin manager service. As a module developer, knowing how to implement an existing plugin type should be considered required knowledge.
Many frameworks use the term “plugin” to describe a bundle of code and other elements that can be installed in order to get access to the features they provide. In Drupal these are called modules, and plugins are one of the ways a module can add new features.
Example tasks
- Define a custom block in a module
- Add a new field type, widget, or formatter
- Create a custom content entity type
- Define a new plugin type in order to allow other modules to extend your module’s capabilities in the same way Drupal core is extended
- Define custom Views plugin
Confidence
Plugins were introduced in Drupal 8. The process for implementing plugins is relatively unchanged since before Drupal 8 was released, so older examples are likely to still be relevant.
Drupalize.Me resources
Prerequisites
Annotations are specially-formatted PHP docblock comments that are used for class discovery and metadata description. While it is technically possible to use annotations for other purposes, at the moment Drupal only uses them for the plugin system.
In this tutorial we'll look at:
- What annotations are
- The use case for annotations
- How to figure out what you can put into an annotation
By the end of this tutorial you should understand how annotations are used in Drupal and how to write them in your own code.
Dependency injection is a design pattern commonly used in object-oriented software architectures in order to support Inversion of Control.
Tutorials
The Drupal plugin system allows a particular module or subsystem to provide functionality in an extensible, object-oriented way. The controlling module defines the basic framework (interface) for the functionality, and other modules can create plugins (implementing the interface) with particular behaviors. Plugins are grouped into plugin types. Each plugin type is managed by a plugin manager service, which uses a plugin discovery method to discover provided plugins of that type and instantiate them using a plugin factory.
The system aims to make it easy for developers to allow for management of these components via the user interface, giving more flexibility and control to site administrators.
In this tutorial we'll take a high-level look at the problem the Plugin API is solving and provide a starting point for diving deeper into the various components that make up the Plugin API.
The term plugin type is used as a way to provide a generic name for all plugins managed by the same plugin manager. Example plugin types include block, field widget, and image effect. A plugin type doesn't consist of any code that provides specific functionality. Instead, it provides a way to refer to the system and it describes the central purpose of all plugins of that type.
In this tutorial, we'll cover what the term plugin type means and how it is used when talking about Drupal's plugin system. By the end of this tutorial, you'll understand what a plugin type is and be ready to learn how to define a plugin type in a module.
Knowing which plugin types exist and the use case for each is important when it comes to writing modules that extend Drupal's existing functionality. If you want to add additional functionality, you need to first know which plugin type provides that functionality.
In this tutorial, we'll list some of the more commonly-used plugin types and their use case, show where you can find a more complete list of plugin types provided by core, and provide several methods for discovering existing plugins in your Drupal codebase.
Before you can create a new plugin of any type you'll need to figure out where the plugin implementation and its metadata should live in the code base so that the plugin manager can find plugins and examine what functionality instances of the plugin type are expected to provide.
This tutorial contains 2 parts:
- A recipe and example of how to implement a plugin if you already know the plugin type.
- How to figure out a specific plugin type's implementation details.
In this tutorial we'll:
- Provide a recipe for implementing plugins of any type.
- Demonstrate how to figure out where the code and metadata should live for PHP-based plugins.
- Explain how to figure out where YAML plugin definitions should go, and what they should contain.
By the end of this tutorial you should have a recipe for getting started with implementing annotation-based plugins, and YAML-based plugins, and a better understanding of how to figure out the details required to implement any given plugin type.
A plugin manager is responsible for both the definition of a new plugin type, and for listing and instantiating instances of plugins of the defined type.
In this tutorial we'll:
- Define what a plugin manager is
- Create a list of all plugins of a specific type
- Load and instantiate specific plugin instances so we can use them in our code
In order for a plugin manager to locate instances of individual plugins within the Drupal code base it needs to know where to look, and how to interpret the data that it finds. This process is called plugin discovery and can be accomplished in a few different ways.
In this tutorial we'll look at what plugin discovery is doing at a high level, and then talk about the various plugin discovery methods you can choose from when defining a new plugin type.
Learn how the Plugin API takes a given plugin ID and uses it to instantiate and return a fully configured plugin object. In this tutorial we'll look at:
- What factories are, and the role they serve in the Plugin API
- The factories available in core
- Using mappers to dynamically load a plugin when you don't know the ID of the specific plugin you need.
Plugin derivatives allow a single plugin to dynamically generate multiple plugin instances based on configuration or other data. This is useful for situations where user-entered data, or other dynamic configuration, might have an impact on available plugins. Or, put another way, any time you need to be able to dynamically generate plugin definitions.
In this tutorial we'll:
- Define what plugin derivatives are
- Understand the use case for derivatives
- Examine how core uses derivatives in order to demonstrate how you could write your own plugin deriver class
Knowing how to define a new plugin type will allow you to write modules that are more extensible, and more configurable. In doing so you'll learn more about best practices in decoupling code within your module, and get an in-depth look at how the plugin system works. Even if you're not defining a new plugin type in your own module, understanding how the system works will give you more insight into how many parts of Drupal work. This is essential knowledge for anyone developing modules for Drupal.
By the end of this tutorial you should be able to determine if defining a new plugin type is the right solution to your problem, and then understand the steps involved in doing so.
Drupal's field system provides us with a flexible system of adding different types of discrete data to content types. This enables us to create rich content models. The Field API allows us to define these distinct field types by creating a new plugin. These plugins specify a FieldType
annotation. In this tutorial, we'll look at these annotations in detail. We'll look at the implementations of field types from Drupal core. Also, we'll see what a new custom field type would look like.
By the end of this tutorial, you should be able to:
- Understand how field type definitions are created and exposed to Drupal
- Identify the various field types provided by Drupal core
- Understand the requirements for providing a specification for a new field type
Once we've explored the various field types provided by Drupal core, the next component of the Field API to explore is field widgets. Field widgets define how the data structure of the field is displayed on an edit form. When content editors interact with your field type they will be doing so via the field widget you provide. In this tutorial, we'll take a look at the field widgets provided by Drupal core, the plugin type required to define our own custom widget and how we can define multiple widget options for a single field type.
By the end of this tutorial, you should be able to:
- Understand where field widgets fit into the overall Field API
- Implement a custom field widget to support a particular field type
Of the 3 main components of the field system -- types, widgets and formatters -- only 1 has an impact on the actual display of content for end users: field formatters. Field formatters are responsible for taking the data stored by a field and transforming it into the markup that is sent to the browser when an end user views your site.
In this tutorial we'll:
- Look at the role field formatters play in the Field API
- Identify the main components that make up a field formatter
By the end of this tutorial you should be able to define the role of a field formatter plugin.
The Drupal Entity API makes it easy to define new custom content entity types. And in most cases whenever you want to store custom content in Drupal you should use the Entity API instead of making CRUD queries directly to the database. This ensures your code is more consistent, and allows you to take advantage of all the features of the Entity API like access control, Views module integration, and automatic JSON:API support. As well as making it easier for others to extend your custom content by ensuring all the proper hooks and lifecycle events get invoked when new content items get created, updated, and deleted.
In this tutorial we'll:
- Walk through the process of creating a custom content entity
By the end of this lesson you'll be able to create your own custom content entity contained in a module.
Views plugins
The Drupal core Views module architecture is built on top of the Drupal Plugin API. This allows site administrators to pick and choose from a list of options (plugins) to handle all the different parts of a view -- including what to display, what style to display it in, how to order the results, who has access, and more. In the Views UI, any time you're presented with the option to choose something from a list of options you're likely dealing with some type of plugin.
The advantage of a plugin-based design is that all functional parts of the Views module are provided in an extensible object-oriented way. The Views module defines the basic framework, and provides interfaces for other modules to implement, extend, and customize via plugins. Customizations to filters, fields, area handlers, sorts, and relationship handlers start with plugins.
In this tutorial we'll:
- Learn about Views plugins and the role they play
- Explore the different plugin types and their underlying classes
- Get a high level overview of the steps for creating a custom Views plugin
By the end of this tutorial you'll have a solid understanding of the different Views plugin types, what they are used for, and where to start if you'd like to define your own.
Views field handler plugins handle retrieving and displaying data within a view. The Drupal core Views module provides field plugins for all of the core field types, and these work well for many situations where you need to describe custom data sets to Views. For situations where an existing plugin doesn't match your requirements, you can define a custom field handler plugin and alter both the query that gets executed and the rendered output of the data.
This is common for contributed modules that define new field types, or any module using hook_views_data()
to define a dataset to Views where the data contained in a database column may need special handling in order to be displayed as part of a view.
In this tutorial we'll:
- Implement a custom Views field handler plugin
- Extend the default date field plugin and modify the way that it displays a timestamp so that instead of a specific date we get a relative value
By the end of this tutorial you should know how to define a custom field handler plugin and use it in a view.
By default the Views module can display data contained in any field attached to an entity that is exposed in Views, and the content of any database column exposed to Views via an implementation of hook_views_data()
. It's also possible to create pseudo fields. These appear in the Views UI like any other field, but don't map directly to the data stored in a database column and instead allow the data to be preprocessed. This could be performing a calculation, combining multiple fields into one, and much more.
A common example in core is the fields that allow you to perform edit or delete operations on a node. These don't correspond to a specific database column. And they can't be hard-coded because they require dynamic content specific to the node in question. Instead, they are the result of taking the entity ID and combining it with knowledge about the appropriate route for someone to edit the entity and outputting that as a link.
Another example: Imagine a cooking website where you collect cook time and preparation time (prep time) for recipes and want to also display the full time to prepare. In this case cook time and prep time could be fields on the recipe content type and total time could be handled as a calculated output of both fields, added together and converted into hours and minutes. To achieve this, you can create a custom Views pseudo field and specify the calculation and processing logic in the render function.
In this tutorial we'll:
- Learn how to define a custom Views field plugin for a pseudo field
- Attach the created field to node entities, and expose it to display in a view
By the end of this tutorial you should know how to define a Views pseudo field plugin, attach it to the node entity type via hook_views_data_alter()
, and display it in a view.
Filter plugins provide the logic for determining what items to include in a view. They are the equivalent of a WHERE
clause in an SQL statement. Filters can be exposed to the end user, allowing the viewer to enter a value, or select from a list of options, that are used to filter a list. For example, the options at the top of the Content list at /admin/content allow you to limit the list by content type.
Drupal's Views module provides filter plugins that can handle filtering for all core defined field types, as well as generic data types like numbers and strings. In situations where these filters don't meet your functional requirements, or you need a filter for a custom field, you may want to define a custom Views filter plugin. A common real-world scenario is defining a new filter plugin that extends an existing one and adds new possible values or options. For example, providing a relative date filter that allows a user to choose options like Last week or Last month.
In this tutorial we'll:
- Learn how to create a Views filter plugin
- Associate our new custom filter with data exposed to Views so it can be used
- Learn how to use it in a view as an exposed filter
By the end of this tutorial you should know how to create a custom filter plugin and use it in Views.
Sort plugins are responsible for determining how the data in a list created with Views is sorted. Sort plugins are applied to fields. For example, a field might contain numbers and the sort plugin can handle putting the values into ascending or descending order. Typically, sort plugins work by adding to the ORDER BY
clause of an SQL query.
The Views module provides sort plugins for all core field types. This includes handling for most primitive data types like strings and numbers. A typical use case for creating a custom sort plugin is extending an existing sort plugin with new conditions or custom sorting logic. For example, you might need to create an alphabetical title sort that excludes articles like a, an, and the. Or a sort based on combining the values in multiple fields.
In this tutorial we'll:
- Learn how to create a custom Views sort plugin
- Associate our custom sort plugin with a field exposed to Views
- Use the sort plugin in a view to sort a list of Article nodes
By the end of this tutorial you should know how to create a custom sort plugin for the title field.
Area handler plugins are used to determine what is displayed in areas such as the header, footer, and empty text sections of a view. The handlers provided by core cover displaying result summaries, and allowing users to enter in HTML to display. They are already pretty versatile. However, they may require code knowledge to accomplish some specific tasks. If you'd like to have a more specialized area handler that can be reused across multiple views, you may want to look into defining a custom area handler plugin.
In this tutorial we'll:
- Create a custom area handler plugin with settings that can be updated through the Views UI.
- Use the new area handler plugin in a view.
By the end of this tutorial you should know how to define a custom area handler with settings and use it in Views.
When a user creates a view, they can set access rules, and restrict who can see the view. The core Views module allows you to limit access by a user's permissions, or roles. If your project requires custom access rules you can define a custom Views access plugin. This will allow you to determine a user's access based on any custom logic you might have.
In this tutorial we'll:
- Define a custom Views access plugin that determines access based on data stored in a field on the user entity type.
- Learn the difference between access checks for routes and access checks for Views displays, and how to use each of them.
- Use our new custom access handler when defining a view.
By the end of this tutorial you should know how to define a custom Views access plugin and use it to grant access to a view.
Style plugins are responsible for determining how to output a set of rows. Individual rows are rendered by row plugins. Drupal core provides style plugins that include grid, HTML list, table, and unordered list styles. If you need to render the results in a different way, for example as tabs or accordions, or have special markup based on your project requirements, you may want to write a custom style plugin for Views. The advantage of this approach versus overriding the templates in a theme is that you may reuse this plugin in different views throughout the site, or even on different sites.
In this tutorial we'll:
- Learn how to create a custom Views style plugin and render output in the form of an accordion using the HTML5
<details>
element. - Demonstrate how to use a custom style plugin when building a view.
By the end of this tutorial you should know how to declare custom Views style plugins.
Guides
Not sure where to start? Our guides provide useful learning tracks for all skill levels.
Navigate guidesExternal resources
-
Plugin API Guide (Drupal.org)
- Community documentation for the Plugin API. Contains lots of useful information which can be somewhat hard to follow without a defined order. Use this when you have specific questions about plugin implementation, but you already know the basics.
-
Plugin API Documentation (api.drupal.org)
- Developer-centric documentation for the Plugin API. Use this as a quick reference for reminders on how to define a new Plugin or Plugin Type. Or if you want a deep-dive into the code that makes up the Plugin API.
-
Examples for Developers project (Drupal.org)
- Contains the plugin_type_example module which demonstrates how to create a custom plugin type. This also teaches you a lot about how the Plugin API works. This example code was reviewed, updated, and had tests added by Drupalize.Me while creating our own content on the Plugin API. Use this if you want something you can copy/paste as a starting point, or if you learn best from reading code.
-
DrupalCon Los Angeles 2015: An Overview of the Drupal 8 Plugin System (youtube.com)
- Recording of a presentation by Joe Shindelar covering the Plugin API. A good overview of the entire Plugin API, useful for learning some basic terminology, information about why the Plugin API is used, and an overview of how all the parts fit together.
-
Drupal 8 API: plugins (jpstacey.info)
- Written overview of the Plugin API with examples of adding a new plugin type and implementing plugins of an existing type. J-P provides a good overview of the inner workings of the Plugin API, as well as providing information about Annotations and OOP conventions. This is one of the best free written tutorials on Plugins we’re aware of.