If anyone has solutions to any of the issues I describe below, please feel free to leave a comment.
I've now developed two production sites with Drupal 8.6
. This post will cover what went wrong, how my team fixed them, and then some best practices from what we've learned through trial and error.
The first site, in hindsight, was a complete disaster. There's nothing worse than learning Drupal (or anything for that matter) through trial and error while developing a production website. I knew nothing about rendered entities
, view modes
, etc. I constantly battled with the templating. We abused the [theme].module
hooks, instead of using custom modules
to handle functionality.
The second site was much better, although I imagine there is so much more to learn. Our biggest issue was how to effectively use views
when using the ajax
functionality. Our decision to not make certain taxonomies
have actual pages (aka have an accessible alias
), led to many problems when trying to filter them in certain views
.
Localization continues to be a huge issue. If you've ever developed with Drupal, you know it's insanely frustrating configuring and outputting localized content correctly.
Best Practices (from my experience)
Language Configuration
Trust me when I say this:
Figure out your localizations
ahead of time.
You should know before development:
- all the
languages
+language codes
you'll be using - what the
original language
will be for all content
Scenario:
Say you are told the site will be in Canadian English (en-CA
) and Canadian French (fr-CA
). Then a couple weeks before deployment, once all content pop is mostly complete, they want to change the language code
from en-CA => en
.
Here is the problem:
There doesn't seem to be a way to change the language code
once it has been added. Additionally, all content that has the previous language code
as the original language
can't be changed either. Even if you delete the orignal language
node translation
, you still cannot assign another translation
as the original language
.
Ok fine, so you add the new language code
, content pop all of the nodes again with the new language
… and run into another problem. All content in a translation
that is not the original language
that has a repeatable number of values, cannot exceed the original language's
number of entries.
How did we fix this? We haven't. We've thought about updating the database through SQL
statements, but please share your thoughts if you have a better way.
Install Drupal Core w/ Composer
Do yourself a favor and use Composer to install Drupal Core. Upgrading core
is now as simple as:
composer outdated drupal/*
composer update drupal/core --with-dependencies
drush updatedb
drush cr
More information is available on their website.
Install Modules w/ Composer
Same deal as with core
, instead run:
# example
# composer require drupal/[module_name]
composer require drupal/better_exposed_filters
Bonus: Awesome Modules
- Paragraphs - just like ACF for Wordpress
-
Better Exposed Filters - adds more options to the advanced section of
views
- Twig XDebug - add debug points in your twig files (requires XDEBUG to be installed and configured on the server; might do another blog post about this)
-
Path Auto - auto generate / update
node aliases
-
Views Reference Field - use with the
paragraphs
module; allows aview
to be injected anywhere on the page - Devel - for debugging
- Yoast SEO - for SEO; content pop for meta tags
-
Drupal Media - in core as of
8.4
, just install it; adds a much better UX experience for handling media
Use the Drupal Console
& Drush
Executables
Installation Instructions (Use Composer)
To install via composer
, run:
# drupal console
composer require drupal/console:~1.0 \
--prefer-dist \
--optimize-autoloader
# drush
composer require drush/drush
Common usage:
# usage
./vendor/bin/drupal [command]
./vendor/bin/drush [command]
# cache rebuild
./vendor/bin/drush cr
# show watchdog log
./vendor/bin/drupal watchdog:show
# install module
./vendor/bin/drupal module:install [module_name]
# generate module
./vendor/bin/drupal generate:module
Setup Drupal for Local Development
Follow this tutorial to make your local development so much easier.
Use View Modes
View Modes
allow you to define multiple ways (aka templates
) to show the same type of content. The two native view modes are full
and teaser
. You can accomplish 95%
of what you need with those two view modes
alone.
Imagine this scenario: You have a content type of Case Study
. A case study can appear as a single page (full
), inside a view grid (teaser
), and also as a featured case study on another page (featured
).
You can customize the display
of each view mode
individually. For example, let's say the teaser
outputs the title
and description
, but hides the image
you've set up. However, the image
should be shown on the featured
and full
view modes
.
This allows us to leverage 3 different templates and customize the output:
node--case-study.html.twig
node--case-study--teaser.html.twig
node--case-study--featured.html.twig
Use Rendered Entities
Let me save you hours of frustration. Use rendered entities
whenever possible. As I understand it, a rendered entity
is the output of an entity through its selected view mode
.
Imagine the case study featured
example from above. You add a new field to the Basic Page
content type for a reference to a case study. In the manage display
of the Basic Page
, you can change the format
of the case study reference to Rendered Entity
, and select the featured
view mode.
This allows for far less code duplication. You are keeping the rendering of entities separate from the nodes that reference them.
Pro tip: you can also use the rendered entity
and a specific view mode
as the format for a view
. Additionally, in scenarios when you have cannot use the content
format, you can add a field called Content: Rendered Entity
that you can reference this way:
{{ fields.rendered_entity.content }}
Use the Media Module
Yes, it's still experimental, but we haven't had any issues with it. It makes uploading, selecting, and deleting media much easier.
Conclusion
Drupal is very powerful. It allows you to add complex relationships and fields to structure any kind of content. However, there is some higher level functionality that is paramount to understand and implement. Leveraging view modes
, rendered entities
, and other best practices will help you become a better Drupal developer.
This post ending up being way longer than I intended. There are more best practices and tips that didn't make it into this post. Any comments with new insight or solutions are always welcome.
Top comments (4)
It appears you should be able to change the default interface language by:
Also, you can change the language code for entities by either:
$node = Node::load($nid);
$node->get('langcode')->value = 'da';
$node->save();
Sources:
That being said, you would still need to change the actual content to the new language, as well (manually).
Thanks for the great post. I work on a legacy Drupal 7 site and my team is in the process of moving to 8 by next year. It's an arduous undertaking, and I'm still not quite up to speed with 8, but will take your notes on getting localization right out of the gate.
I do really like the standard serialization module in 8 for composing views in JSON.
I’m glad you found the post useful. Definitely a good call on figuring out localization first, we are still uncovering more hidden issues once we used SQL Statements to change the default language.
Interesting you mentioned the core serialization module; I started on D8 so I don’t know any of the downfalls of D7. I’m glad you’re finally making the switch.
Good luck with everything.
Hey Michael, very useful post... 😊
BTW I am only 3 months old to drupal so just wanted to ask.
,how to create a config form in drupal 7.
With api calling... If you can help.
Thank would be gr8.