Create a custom Twig filter in Drupal 8
Thoughts on the Acquia Certified Developer - Drupal 8 Exam
Another year, another Acquia Certification exam...
I'm at DrupalCon New Orleans, the first North American DrupalCon since the release of Drupal 8. In addition, this is the first DrupalCon where the Acquia Certified Developer - Drupal 8 Exam is being offered, so I decided to swing by the certification center (it's on the 3rd floor of the convention center, in case you want to take any of the certification exams this week!) and take it.
LevelTen and Dries Keynote at DrupalCon New Orleans 2016
The LevelTen Team takes New Orleans! Read through our Twitter feed as we experience the opening ceremony of #DriesNote with the Drupal Community.
[View the story "Dries Note at DrupalCon New Orleans" on...Read moreWeb Chefs Wild at DrupalCon 2016
The Four Kitchens gang has landed— #4KNOLA! …
Drupal 8 Theming Tutorial: How to Craft Custom Theme Hook Suggestions and Templates
I've been theming with Drupal since version 6 back in 2009. In the intervening years, I've seen a lot of changes of how theming and front-end development is approached and have tried to keep up with the latest trends and adhere to best practices. Drupal 8 takes theming to a whole new level; it feels elegant, freeing, uniform, cohesive, and logical. So there's a lot to get excited about here.
In Drupal 8, there's templates for just about anything and with Drupal 8's new theme hooks, you can really narrow in on crafting a custom template for your specific use case. This makes getting at and altering markup far more accessible than it was in Drupal 6 and 7.
My preferred method for Drupal 8 theming is using Classy as my base theme, creating a sub-theme off of that and then overriding the parts that are necessary. An override is as simple as copying one of Classy's 100+ templates into your Classy based sub-theme. Sometimes, an out of the box template is not enough so you can create your own theme hook in that case.
In this post, I'll help you get started with creating Drupal 8 custom theme hook suggestions and templates. I also refer to various tools that I use, you can read more about them in my article, Drupal 8 Development: 5 Things to Add to Your Theming Toolbox.
OverviewThe goal for this tutorial is to create a theme hook and subsequent template for a group of block regions in our site. The regions are called postscript_one
, postscript_two
, and postscript_three
. The Drupal API function we will use for this is hook_theme_suggestions_HOOK_alter
where "HOOK" is the name of the theme hook that we see in our Twig debug area. So essentially, we'll grab this theme hook and make a template suggestion for an array of these regions.
To start off, I'll place a block in one of my postscript regions and then examine the placed block with Web Inspector. Here is what I see when we do that:
<div class="postscript">
<!-- THEME DEBUG -->
<!-- THEME HOOK: 'region' -->
<!-- FILE NAME SUGGESTIONS:
* region--postscript-second.html.twig
x region.html.twig
-->
<!-- BEGIN OUTPUT from 'themes/custom/hibiscus/templates/layout/region.html.twig' -->
From the above, we see the theme hook name, region
as well as a two template suggestions. What I am after here is a common region template for any of the the three postscript regions that I mentioned earlier. Time to fire up Devel Kint and see what we can learn by inspecting the region array. For this, I will initiate my theme hook function in my theme's .theme file
. Of note is hibiscus
, my Classy sub-theme theme name and the HOOK
, "region".
/**
* Implements hook_theme_suggestions_HOOK_alter().
*/
function hibiscus_theme_suggestions_region_alter(&$suggestions, $vars, $hook) {
}
Now I'll enable kint()
as kint($vars);
:
function hibiscus_theme_suggestions_region_alter(&$suggestions, $vars, $hook) {
kint($vars);
}
After I run drupal cr all
using Drupal Console, I'll now see kint print out the region array on my page. As you can see from the below image.
Using Kint search, we can search for and copy the path for the region name definition, $var['elements']['#region']
It is from this that we will construct our array of regions and subsequent theme hook. First I define the region name variable from the above:
$region = $vars['elements']['#region'];
Now I'll define an array of my three regions:
$region_postscript = array(
'postscript_first',
'postscript_second',
'postscript_third',
);
Next I construct an if statement to make the actual theme suggestion:
if (in_array($region, $region_postscript)) {
$suggestions[] = 'region' . '__' . 'postscript';
}
What this does is say, if it's any of the three postscript regions, create a theme hook that's common to all these regions.
Putting it all togetherPutting the entire function all together, we now have:
/**
* Implements hook_theme_suggestions_HOOK_alter().
*/
function hibiscus_theme_suggestions_region_alter(&$suggestions, $vars, $hook) {
// Define a variable for the #region name.
$region = $vars['elements']['#region'];
// Define an array of our postscript regions.
$region_postscript = array(
'postscript_first',
'postscript_second',
'postscript_third',
);
// If we are in any of these regions, create a theme hook suggestion.
if (in_array($region, $region_postscript)) {
$suggestions[] = 'region' . '__' . 'postscript';
}
}
Now that I have written my theme hook, I can clear cache and reload the page to see my new theme hook suggestion in action.
<!-- FILE NAME SUGGESTIONS:
* region--postscript.html.twig
* region--postscript-second.html.twig
x region.html.twig
We now see out new template suggestion from our custom theme hook, region--postscript.html.twig
. This template would be common to all three regions so we can alter or update the markup in this new template as well as add classes as we see fit. Since I have a Classy sub-theme in my case, I copy Classy's region.html.twig and rename it to the new name within my own sub-theme folder structure. Of course if you are using stable as your base theme, you would do the same thing copying stable's template of the same name.
This is just a basic example to show what's possible with creating Drupal 8 theme hooks and template suggestions. Hopefully you can see that it's really useful and should come in handy for themers.
Tags- Drupal Planet
- Drupal
- Preprocess
- Drupal 8
- Twig
- Theming
Drupal 8 console & Composer faster site development
One of our OSTraining members asked what was the best way to install composer to manage dependencies.
While composer can be used to add module dependencies into drupal. It's more practical for DrupalConsole to handle the process. Console automatically passes the requests to composer.
From the terminal command line running the following commands will install both Console and Composer together.
How to Create a Search Page in Drupal 8
Building a search page isn't as straight forward as you'd think. At first a client will want something which users can search content, then they may want to modify the search results or even change the ranking of certain content. Long story short, something you thought would be as simple as enabling a module, ends up taking twice as long.
If you need to create custom search pages in Drupal 7, more often than not, you use [Search API](https://www.drupal.org/project/search_api) or create a [search page using Views](https://www.webwash.net/node/84). But the core Search module for Drupal 8 has become more powerful than in Drupal 7. One of the big changes, for site builders, in Drupal 8 is the ability to create custom search pages.
However, there're a few limitations to creating a search page. First, it'll have a prefix of "search/" in front but the full URL can be changed by creating a URL alias. Second, you can only adjust the content ranking on these pages. If you want to index extra fields or remove ones from being indexed, you'll still need [Search API](https://www.drupal.org/project/search_api) to do this.
In this tutorial, you'll learn how to create a custom search page and how to modify the search results by overriding a template.
Core topic discussions at DrupalCon New Orleans
DrupalCon New Orleans includes a full track of core conversations where you can learn about current topics in Drupal core development and participate in shaping Drupal's future.
In addition to the core conversations, we have a few meetings on specific topics for future core development. These meetings will be very focused, so contact the listed organizer for each if you are interested in participating.
Time Topic Organizer Tuesday May 10, 10:00a-12:00p Content Workflow dixon_ Thursday May 12, 12:00p-2:00p REST/API-first improvements prestonso Thursday May 12, 4:30-6:00p Theme component library Wim Leers Friday May 13, 11:00a-12:00p Migrate critical triage (round 2) mikeryan Friday May 13, 12:30p-2:00p Blocks and Layouts tim.plunkettAlso be sure to watch Dries' keynote for ideas about Drupal's future!
Resolving "Fatal error: class not found" in Drupal 7
You have gone through your regular module update routine and cleared the cache. Suddenly you are presented with a PHP Fatal error, because a class can’t be found. Your Drupal site won’t load and you can’t run Drush commands. All you get is the fatal error blocking the site.
If you get a fatal error like above where a class is not found, a likely cause is that the Drupal registry has the old path for the class. A cache clear should update, but sometimes it all goes a bit wrong. The solution is to rebuild the registry. This will update the registry table with the new file locations. Read on to find out how...
Query for nodes which reference multiple terms in Drupal 7
Have you ever needed to run a custom query that returns all the nodes which reference two or more taxonomy terms? I have, and most of the time it was very simple because the requirement was for nodes which reference either term, rather than ALL the terms.
When we are dealing with an OR type of select query, it couldn't be easier:
$query = db_select('node', 'n'); $query->join('taxonomy_index', 'ti', 'ti.nid = n.nid'); $query->condition('ti.tid', array(1, 2)); $query->fields('n', array('nid')); $result = $query->execute();
The above example keeps things simple by assuming the term reference maintains an index in the taxonomy_index
table and that we already have our term IDs.
Things get a bit more complicated when we are trying to query the nodes which reference both term 1 AND term 2. After banging my head against the wall for a bit, I came up with a solution inspired by how Views generates its query:
$tids = array(1, 2); $query = db_select('node', 'n'); foreach ($tids as $key => $tid) { $query->innerJoin('taxonomy_index', 'ti_' . $key, 'ti_' . $key . '.nid = n.nid AND ti_' . $key . '.tid = ' . $tid); } foreach ($tids as $key => $tid) { $query->condition('ti_' . $key . '.tid', $tid); } $query->fields('n', array('nid')); $result = $query->execute();
So basically the solution is to create a join for each term ID we want to filter by. A crucial part of this is that the join needs to happen on the node ID between the two tables (as expected) but also on the term ID we are using for the filter matching the record in the taxonomy_index
table. This will ensure that the two joins are not the same but that they reflect the relation between the node record and each individual term ID. Are you still following? Then, we just add our conditions on the newly created joins.
This should work, and depending on the size of your dataset, it should not have too much of a performance impact. However, as no joins should be done if not absolutely necessary, investigate the possibility of querying for the nodes that reference the first term and then filtering the rest out using PHP. This can be a viable option if you know that usual result sets are not too big so you are not running array_filter()
on 2000 terms. And of course, when possible, cache the query appropriately.
Web service requests via snakes and spiders
First off, hope you are all enjoying Drupalcon, super jealous.
Its been almost three months since I wrote about Creating secure, low-level bootstraps in D7, the gist of which is skipping index.php when you make webservice calls so that Drupal doesn't have to bootstrap as high. Now that I've been playing with this, we've been starting to work on a series of simplied calls that can propagate data across the network in different ways.
Dropcast: Episode 19 - DRUPALCON!
The title says it all. This episode we talk to Shellie Hutchens about all the great things we will be doing in New Orleans without Mario and Bob. As usual we have the Pro Project Pick and the Final Bell, Drupal news and some great discussions around Mark’s other project, the Friday 5.
Search Strategies in Drupal 8
Hatching your Search strategy for Drupal 8?
You're in luck.
You can tap into two recent blog posts -- one new, one refreshed -- and get a good idea of the State of Search in Drupal 8.
Tags: acquia drupal planetBattleplan for Search & Solr in Drupal 8
tl;dr
Contrib Search maintainers are committed to make Drupal 8 kick ass with Search API.
Search is a massively cool technology spectrum with loads of really tough problems such as language stemming, delivering search as a site scales and helping customers actually find what they want. However, solving these is not so easy. Let’s look at the history of Search and Solr in Drupal.
Tags: acquia drupal planetA hundred thousand welcomes from Drupal Ireland
Drupal Ireland offers you a “céad míle fáilte” - a “hundred thousand welcomes”!
Come join us for DrupalCon in Dublin which promises to be a fantastic event, held right in the heart of Dublin city.
Adding the node class to a body HTML tag in Drupal 8
Doing some hacking at DrupalCon New Orleans and my use case is to add a node-* class to the body HTML element in Drupal 8. With the preprocess hook in D8 it looks like there is access to different variables than previously. To get the node id one has to look at the cache tags. Here's how I did it:
In mytheme.theme:
D8 and Drupal’s Destiny on the Open Web
Michael Schmid presents their amazee-ing Drupal Security
Michael Schmid , Group CTO at Amazee, conduces his team with creativity and an amount of know-how you wouldn’t think his age would possess! Amazee Labs, a web-hosting, web-consulting and development company, started their Drupal security of 2016 with Drop Guard. And amazee.io the just launched Drupal Hosting platform built for develeopers, which has a full integration into Drop Guard.
Drupal Drupal Planet Security InterviewCreate Apache2 Virtual Host using Shell Script
The ability to create and utilize tools, makes human race dominant in world. Tools make our work easier and also saves time. One of the tools, I am going to share is bash shell script to create apache2 server virtual host.
Why Virtual Host?
Using virtual host we can run more than one web site (such as dev.drupal-cms.com, stage.drupal-cms.com and www.drupal-cms.com) on a single machine. It can be "IP-based" or “name-based”. In IP-based you can have different IP address for each web site. In name-based you can have multiple names running on each IP address.
Shell script code
Explanation
Script expects 3…