As you start down the road of learning Drupal 8 module development, one of the first new Drupalisms that you're likely to encounter are plugins. After writing a blog post about creating blocks, which uses the new plugin architecture, I thought it might be interesting to take a step back and talk a little bit more about plugins at a higher level. This blog post contains an introduction to the what and why of plugins to help Drupal 7 developers make the transition to Drupal 8.
What are Plugins?
Plugins are a new concept in Drupal 8 that will be important for any aspiring Drupal 8 module developer to understand. Some common use cases where you'll encounter plugins are defining custom blocks, providing custom field API fields, and each of the effects you can perform on an image such as scale or rotate. Here's what the Drupal handbook has to say about plugins:
The D8 plugin system provides a set of guidelines and reusable code components to allow developers to expose pluggable components within their code and (as needed) support managing these components through the user interface.
Situations in which plugins are useful? Anytime you need to allow modules to provide additional "things" that implement the same interface but provide distinctly different functionality. Blocks are the classic example. In Drupal every block consists of essentially the same parts, a label, some content, and various settings related to visibility and cachability. How that label and content is generated is likely very different from one module to the next though. A custom block with static content vs. one provided by Views for example.
Each plugin behaves the same way externally (to any code that's using it) but internally can vary wildly from one to the next. As long as it sticks to the requirements about what it's external face should look like as set forth by the plugin type that's being implemented.
What are Plugin Types?
Plugins that perform similar functionality are of the same plugin type. All blocks for example are plugins of the block plugin type.
Plugin types are the contract you sign where you agree that you'll build your new functionality to a certain specification, ensuring that the plugin manager will know how to interface with your plugin to get the data it needs, or ask it to perform a given operation.
The plugin type controller (or plugin manager) determines how plugins of a given type are discovered, and instantiated. The most common form of plugin discover is annotated plugin discovery. Follow the PSR-4 standard for where your plugin file should live and the plugin manager will take care of locating and instantiating that plugin as needed using the included annotations for an meta-data required.
In addition to implementing plugins of an existing plugin type modules can also provide their own new plugin types allowing other modules to enhance or extend their functionality in the same way that core does.
Why Plugins Are Awesome?
At the end of the day the plugins you write are in implementation of a PHP Interface. And this has huge implications on our ability to understand how each plugin works, what code you're required to write and what other optional operations you might perform. In Drupal every plugin type has a set of requirements that a plugin needs to fulfill in order to perform whatever operation it is that the plugin manager expects that plugin to be able to do. Having these all grouped together as methods on the same interface makes it much easier for a developer to quickly scan and understand how this particular plugin type works.
If you've ever needed to implement a custom block in a Drupal 7 module before then you're familiar with Drupal 7's hook based approach to solving this same problem. You can declare to Drupal that your module has a block by implementing
hook_block_info() and providing meta-data about your block. But that's not enough, you'll also need to implement
hook_block_view() in order to provide the content for your block. Want to allow an administrator to add some custom settings? You'll need another hook to add elements to the settings form and yet another to save that data. All of this is held together by convention, and you only know you need the other hooks because the documentation said so. When you know the pattern it's not that hard, but the first time you have to create a custom block figuring out what all the hooks are that you need to implement can be challenging.
Want to have your module provide more than one block? Now you've got switch statements inside of each of these hooks to figure out which of the many blocks your module provides is being operated on currently.
Plugins on the other hand encapsulate all of this into a single PHP file per block. The meta-data about the plugins is provided by Annotations in the @docblock for the plugin class. It's easy to discover that you can implement the
label() method to return the human readable label for the block, or the
build() method to return the blocks content, because it's declared right there on the BlockPluginInterface that you're implementing. Many IDE's can even discover and autocomplete these public methods for you. Making it much easier for a someone new to block plugins to gain an understanding of how to provide a block.
For me, the biggest win at least initially is the improved developer experience of having all the related code in one place. One php file, one block. As well as now having a single unified way of handling this type of "my module wants to also provide an X" scenario that's so common in Drupal. Learning the plugin system, and you'll know how to provide functionality to the 20+ things that use it instead of having to learn a new pattern for each one.
Some additional reading and resources on Drupal 8 plugins:
- Unravelling the Drupal 8 Plugin System
- Blog post defining plugins - http://www.drupalism.com/tutorial/what-plugin-system-drupal-8
- DrupalCon Portland presentation on plugins - https://www.youtube.com/watch?v=T5y3dJYHb_A&feature=youtu.be
- Blog post with more focus on the technical aspect of implementing plugins - http://www.previousnext.com.au/blog/understanding-drupal-8s-plugin-system