Khanh Hoang - Kenn
Kenn is a user experience designer and front end developer who enjoys creating beautiful and usable web and mobile experiences.
During my first year of being a full time Drupal developer, I ran into quite a few stumbling blocks. Here are 14 of them that you don't want to trip over too - whether you are new to Drupal or a seasoned expert.
I have just completed my first year as a full time Drupal developer. It has been an interesting year, I have learned a lot and continued to be impressed as to how productive you can be with Drupal. Time and again I have started a user story thinking it could take days or even weeks, but then finished it by a few clicks of my mouse. I am also very grateful to my awesome colleagues that have patiently pointed me in the right direction more than once.
There have been some surprises along the way, to a guy that has worked with web development for some ten years before starting with Drupal for real.
I have made a list of these for myself, titled Drupal gotchas. These are stumble blocks, or counterintuitive things that developers could benefit from knowing about when they meet Drupal for the first time.
They are not necessarily bugs, it is just nice to know about them in advance.
Most developers use drush, and we use drush cc all
a lot to clear drupal’s caches during development. But sometimes, just sometimes, that doesn’t help. Try logging on to drupal in your browser and clear the cache. Just because .. it would be too easy otherwise?
If you on your local env have some taxonomy, user role or permission that is not on the other end, and try to export permissions regarding one that is the newest, there will be lots of SQL errors on the other end.
Cause: Taxonomy permissions, user roles and permissions are put into feature based on their id numbers from the database, and not the name as you would expect.
Removing a field or field group from a content type? It won't be removed when you do a feature revert on the target.
This is probably what you want in many cases; having features module delete fields might lead to unwanted data loss.
When removing fields from a project, you should either do it through an update hook or manually delete them from all environments.
Oh, so you have a date field, and you decide that you want to collect the end date? Well, if there is content in the database, sorry it can't be done. It’s not like the project’s requirements will ever change, you know.
I received a comment from Olli about this one which I think it is important to keep in mind:
Well, technically, it can be done. It just requires a manual change to the database. And filling in the missing end dates too. So, quite a bit of work instead of a simple field edit in the UI.
If you use entity translation, and it is sort of your first time you are creating a view with this, you should print out this comment from Fabsor and hang it on the wall before you start:
"You can add a relationship to the entity translation table, and from there you can add entity translation: language as your filter. This filters out entities on a specific language."
In a vanilla Drupal installation, without any contributed modules installed, I would really want to be able to let editors add content and edit content, and even publish it on their own, but not delete anything.
Can you manage that?
If you grant the “Administer Content”-permission they will also be able to delete content.
So is the machine name main_menu or main-menu? Not that consistent.
(From Cristian)
This might be trivial but it's good to remember: when doing ajax forms
"wrapper" => "form_id" is wrong
but "wrapper" => "form-id" is correct
Sometimes CSS block views classes turn into md5 hashes, which can be quite annoying in several situations, for instance when writing CSS for a project. Instead of having developer friendly machine names as selectors, you end up with md5 hashes in your CSS.
merlinofchaos’ explanation was spotted by Joonas M:
This is not a random ID, it's an md5 hash. The reason md5 hash is used here is that it is guaranteed to be 32 characters or less.
The 'delta' field of a block is limited to 32 characters. However, the only guaranteed unique way of identifying a view and a display takes as many as 65 characters (32 characters for the view name, up to 32 characters for the display id, and a character to separate them, which is a dash). If this combination is 33 characters or longer, an md5 hash is used instead. It was the only solution I could come up with that functioned.
If you don't like the md5 hash, use shorter view names.
This I learned in a caching session at drupalcon Prague:
If you turn on caching of pages for anonymous users, and an anonymous user adds a comment or something, all those caches are cleared.
This one is the fantastic t()
function GOTCHA. I stumbled on it more than once..
I found a helpful comment by span:
It should also be noted that the string is not added to the database until it has been displayed in a language that is not the default. It is not enough to only display the string in the default language to be able to translate it via 'Translate interface'.
And Nick_vh:
"If you're visiting the Default language (mostly English) version of the site the translation table doesn't get populated... t() just output the passed string without accessing the DB. "
in the API documentation for Drupal 6.
And just now, in the same documentation for Drupal 7 I saw an interesting tip from jonathanpglick on how to get the strings programmatically into your system which I am looking forward to try:
If you want to get a string into the translate interface programmatically (without displaying the page containing it) you can call:
locale($string,'');
The empty string as the second argument is important!
So you are making a custom block whose content depends on some variables, for instance $_GET
ones, and you have turned on .. role based caching of your block (which is default)?
Well, then you are in for a surprise - Drupal will cache contents of the block as it is shown to the first visitor with their variables and show it to everybody with the same role.
In this case a DRUPAL_NO_CACHE
directive for the block solved the issue, and I have a mental note about the caching from this point on.
This GOTCHA turned out to be wrong, as pointed out in the comments, so I have changed it. So I had this nice learning experience where I wanted to turn off caching with redis together with a colleague, and instead use the default drupal cache. We had some issues with caching not clearing properly (due to a bug in the metatag module, now patched).
I commented out the redis cache config in in settings.php
:
;$conf['cache_default_class'] = 'Redis_Cache'; //do you spot our mistake?
But nothing changed! The problem was still there, and yes Drupal was still using redis as cache backend even though there was nothing in the config file to tell it to.
Then we thought that we had to add
$conf['cache_default_class'] = 'DrupalDatabaseCache';
into the config file too for it to work. Thinking that the problem was that Drupal doesn’t revert to the default state by itself as you might have expected from other config files. But as Damien points out in the comments, using ; to comment out lines doesn't work in settings.php - it is a php file! A quick test on my local environment, where I comment out the Redis lines in settings.php using // seems to revert back to the database cache.
This Gotcha is provided by Ilmari:
In memcached, a single cache entry is limited to 1Mb. Memcached itself won’t show up any error if something doesn’t fit in it, it will just act as if there was no cache at all for that entry, which can make a site very slow.
Cache bins that most often contain entries over 1Mb are those of views. That is why views bins would be the primary item I would/have put in Redis instead of memcached.
This is a configuration example:
# Cache bins. First cache_views, that doesn’t fit in memcached, and takes up to 30-40% CPU time of total when in MySQL. Redis works best. $conf['cache_class_cache_views'] = 'Redis_Cache'; $conf['cache_class_cache_views_data'] = 'Redis_Cache';
Phew, that was it. Have you stumbled into another one? Please add it in the comments, so that other people will not have to spend those frustrating hours too!