For Drupal 7, I have a pattern to help simplify creating and managing custom blocks for a site. Since the standard hook_block_info()
and really hook_block_view()
implementations tend to get messy and junked up with markup in the code. My solution was the use the block delta key from the block info array as a helper function name called from the hook_block_view()
, and a theme function in hook_theme()
to make sure I could easily create a template for each block. I’m not going into detail about it since was hardly original and I’ve seen several variations from other developers.
When I started to work on Drupal 8 I wanted to develop a similar pattern to help create simple conventions for integration with front end work on a project. While the new plugin system helps avoid the ugliness of old hook_block_view()
implementations, how to create a twig file for your custom block isn’t obvious and doesn’t impose a naming convention. Worse, I’ve seen lots of example code with blocks that return render arrays of type markup meaning they have HTML in strings in PHP.
Most projects involve a collection of nearly static blocks that provide basic information like the copyright information, a disclaimer text, a link to the firm that built the site, decorative flourishes, and other similar elements that don’t benefit from being managed as content. After a couple experiments I’ve come up with a solution that works pretty well:
- Create a module for simple blocks (although I use the rest of the pattern anytime I’m creating a custom block).
- Create the block class for each block within the module at
src/Plugin/Block/CopyrightBlock.php
. - Create a theme function for each block in the main .module file.
- Create a twig file to implement the theme function within the module at
templates/custom-blocks-copyright.html.twig
.
The for a copyright block the class itself is simple. We implement the variables we want rendered by the block, and set the cache to expire at midnight (one of the places a timed cache makes more sense that cache tags):
With the block created, we need to define the custom_blocks_copyright
theme function we included in the block using hook_theme()
from within the dot module file. Remember any custom variables you used in the block class need to also be defined here (in this case attributes and year):
Finally, create the twig file to provide the actual markup.
Why do not you put a full path to files you mention in your review? This is probably one of most important things for those who will follow your instructions.
I still have these questions after reading: where should I put a twig template? where should be placed block class? etc. These details would made your instructions much easier to follow.
The graphic of the directory is meant to convey the relative paths. I’m sorry you found that unclear and frustrating.
Reading back I do see I failed to make sure that information is available at all to screen readers which is a fairly big oversight on my part. I’ll update to try to make the text clearer and more useful to people using accessibility technologies.
That said the paths will still be relative the module’s directory since full system path vary a great deal, even the path from Drupal root can vary depending on how you setup your site.
The tutorial helped me a lot, but I have a question, if I want to create another block with its own theme in the same module, how can I do it? I should create another class or it can be done in the same file, thanks.
To create a second block you create a second block class (one class per file), another key in the theme array with variables for the second block (this stays in the hook_theme defined above), and then finally another twig file to generate your HTML (again new file).
Are you using a similar pattern in D8?
Jeremy,
It’s great to hear from you, I hope you’re doing well at Back Office Thinking — tell Paul I say hello.
This is the pattern I came up with when 8 was new, and has severed me well since. It may look familiar since you’ve seen many of the D6 & 7 sites it was inspired by, but the need to support the plugin classes in D8 required some changes from those older patterns.
You could probably take this a step further, and get a list of block plugin IDs for the module during the hook_theme to populated the array with really basic stub theme functions, but you wouldn’t be able to easily control the variables on a block-by-block basis without additional work so I’m not sure it would gain you anything of value.