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 codesyou'll be using - what the
original languagewill 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
paragraphsmodule; allows aviewto 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.