Drupal 8.x - What I've Learned
Tags: drupal
Published: 2019-01-13 19:39:07

---
title: Drupal 8.x - What I've Learned
published: true
description: What I've learned from developing in Drupal 8.x. 
tags: drupal
cover_image: https://res.cloudinary.com/michaeldscherr/image/upload/v1547399750/Dev.to/Posts/Drupal%208.x%20-%20What%20I%27ve%20Learned/devto-drupal-what-ive-learned_zvwre1.jpg
---

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`&#8230; 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][install-drupal-with-composer]. Upgrading `core` is now as simple as:

```shell
composer outdated drupal/*

composer update drupal/core --with-dependencies
drush updatedb
drush cr
```

More information is available [on their website][update-drupal-with-composer].

### Install Modules w/ Composer

Same deal as with `core`, instead run:

```shell
# example
# composer require drupal/[module_name]

composer require drupal/better_exposed_filters
```

#### Bonus: Awesome Modules

- [Paragraphs][drupal-module-paragraphs] - just like [ACF for Wordpress][advanced-custom-fields]
- [Better Exposed Filters][drupal-module-better-exposed-filters] - adds more options to the advanced section of `views`
- [Twig XDebug][drupal-module-twig-xdebug] - add debug points in your twig files (requires [XDEBUG][xdebug] to be installed and configured on the server; might do another blog post about this)
- [Path Auto][drupal-module-path-auto] - auto generate / update `node aliases`
- [Views Reference Field][drupal-module-viewsreference] - use with the `paragraphs` module; allows a `view` to be injected anywhere on the page
- [Devel][drupal-module-devel] - for debugging
- [Yoast SEO][drupal-module-yoast-seo] - for SEO; content pop for meta tags
- [Drupal Media][drupal-module-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)

- [Drupal Console Docs][drupal-console-docs]
- [Drush Docs][drush-docs]

To install via `composer`, run:

```shell
# drupal console
composer require drupal/console:~1.0 \
    --prefer-dist \
    --optimize-autoloader

# drush
composer require drush/drush
```

Common usage:

```shell
# 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][drupal-local-development-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:

```php
{{ 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.

[install-drupal-with-composer]: https://www.drupal.org/docs/develop/using-composer/using-composer-to-manage-drupal-site-dependencies
[update-drupal-with-composer]: https://www.drupal.org/docs/8/update/update-core-via-composer
[advanced-custom-fields]: https://www.advancedcustomfields.com/
[drupal-module-paragraphs]: https://www.drupal.org/project/paragraphs
[drupal-module-better-exposed-filters]: https://www.drupal.org/project/better_exposed_filters
[drupal-module-easy-breadcrumb]: https://www.drupal.org/project/easy_breadcrumb
[drupal-module-twig-xdebug]: https://www.drupal.org/project/twig_xdebug
[drupal-module-path-auto]: https://www.drupal.org/project/pathauto
[drupal-module-viewsreference]: https://www.drupal.org/project/viewsreference
[drupal-module-devel]: https://www.drupal.org/project/devel
[drupal-module-yoast-seo]: https://www.drupal.org/project/yoast_seo
[drupal-module-media]: https://www.drupal.org/project/media
[xdebug]: https://xdebug.org/
[drush-docs]: http://docs.drush.org/en/master/install/
[drupal-console-docs]: https://docs.drupalconsole.com/en/getting/composer.html
[drupal-local-development-tutorial]: https://www.drupal.org/node/2598914