Monday, 15 April 2019

Drupal 8 Certification Guide


Drupal 8 Certification Study Guide

Notes based on the Acquia Certified Drupal 8 Developer Study Guide and other resources.
For the record, I officially passed my exam on 4/24/2017 at DrupalCon Baltimore.
Feel free to open PRs, adding new info and correcting any mistakes you may find.
It is highly recommended that you also read the Drupal 8 User Guide as much of the site building section (including the missing notes in this repo) covers what is in the user guide.
Update: 4/2/2018: I'm presently studying for both the Front End Specialist and Back End Specialist exams and have started updating the documentation to go a bit more in depth on certain topics. The material is all still relevant for the general developer exam, but may be a little more detailed than you need. Either way, I feel like it's important information to know regardless of whether or not it is asked on the certification exam.
Update: 4/9/2018: I've successfully completed both the front end and back end exams. As to avoid giving anything specific away, I will say this study guide does have pretty decent coverage for both, but there are a few things missing.
On the front end, it's a bit important to familiarize yourself with some of the newer aspects of HTML5 if you came from a XHTML background. I'll also say just knowing about the breakpoint module isn't enough from a performance perspective. Also, it helps to know some of the more advanced features in Twig, even if you don't use them every day. I highly recommend reading The Drupal 8 Theming Guide. It is a rather helpful resource and definitely proved to be beneficial to me.
On the backend, the best thing you can do is just build a module or two. We could add all kinds of things to the study guide, but nothing beats actual experience here. I'd also emphasize knowing the differences between plugins and services, and different ways you might validate and sanitize user input in a variety of contexts.

This study guide used in tandem with the 'Drupal 8 Certification Crash Course':

PRs Welcome!
Disclaimer: This is not officially related to the Acquia certification process. These notes are just based on what I thought was important while I studied. Your results may vary.



HTML/CSS

HTML/CSS is a very large subject matter, and the presumption is that you understand at least the bare essentials to take the certification exam, and there are plenty of places to learn HTML/CSS online. As such the notes for this section only cover some specific topics.

HTML5 Tags

TagDescription
<article>Defines an article
<aside>Defines content aside from the page content
<details>Defines additional details that the user can view or hide
<figcaption>Defines a caption for a <figure> element
<figure>Specifies self-contained content, like illustrations, diagrams, photos, code listings, etc.
<footer>Defines a footer for a document or section
<header>Specifies a header for a document or section
<main>Specifies the main content of a document
<mark>Defines marked/highlighted text
<nav>Defines navigation links
<section>Defines a section in a document
<summary>Defines a visible heading for a <details> element
<time>Defines a date/time

CSS Specificity

A selector's specificity is calculated as follows:
count the number of ID selectors in the selector (= a) count the number of class selectors, attributes selectors, and pseudo-classes in the selector (= b) count the number of type selectors and pseudo-elements in the selector (= c) ignore the universal selector Selectors inside the negation pseudo-class are counted like any other, but the negation itself does not count as a pseudo-class.
Concatenating the three numbers a-b-c (in a number system with a large base) gives the specificity.
Examples:

*               /* a=0 b=0 c=0 -> specificity =   0 */
LI              /* a=0 b=0 c=1 -> specificity =   1 */
UL LI           /* a=0 b=0 c=2 -> specificity =   2 */
UL OL+LI        /* a=0 b=0 c=3 -> specificity =   3 */
H1 + *[REL=up]  /* a=0 b=1 c=1 -> specificity =  11 */
UL OL LI.red    /* a=0 b=1 c=3 -> specificity =  13 */
LI.red.level    /* a=0 b=2 c=1 -> specificity =  21 */
#x34y           /* a=1 b=0 c=0 -> specificity = 100 */
#s12:not(FOO)   /* a=1 b=0 c=1 -> specificity = 101 */

!important

When an important rule is used on a style declaration, this declaration overrides any other declarations. Although technically !important has nothing to do with specificity, it interacts directly with it. Using !important, however, is bad practice and should be avoided because it makes debugging more difficult by breaking the natural cascading in your stylesheets. When two conflicting declarations with the !important rule are applied to the same element, the declaration with a greater specificity will be applied.
Some rules of thumb:
  • Always look for a way to use specificity before even considering !important
  • Only use !important on page-specific CSS that overrides foreign CSS (from external libraries, like Bootstrap or normalize.css).
  • Never use !important when you're writing a plugin/mashup.
  • Never use !important on site-wide CSS.

CSS Source Order

If multiple competing selectors have the same importance and specificity, the third factor that comes into play to help decide which rule wins is source order — later rules will win over earlier rules.

CSS Combinators

Using one selector at a time is useful, but can be inefficient in some situations. CSS selectors become even more useful when you start combining them to perform fine-grained selections. CSS has several ways to select elements based on how they are related to one another. Those relationships are expressed with combinators as follows (A and B represent any selector seen above):
NameSyntaxSelects
Group of selectorsA, BAny element matching A and/or B (see Group of selectors on one rule, below - Group of Selectors is not considered to be a combinator).
Descendant selectorA BAny element matching B that is a descendant of an element matching A (that is, a child, or a child of a child, etc.).
Child selectorA > BAny element matching B that is a direct child of an element matching A.
Adjacent sibling selectorA + BAny element matching B that is the next sibling of an element matching A (that is, the next child of the same parent).
General sibling selectorA ~ BAny element matching B that is one of the next siblings of an element matching A (that is, one of the next children of the same parent).


Javascript/jQuery

Javascript is a very large subject matter, and the presumption is that you understand at least the bare essentials to take the certification exam, and there are plenty of places to learn Javascript online. As such the notes for this section will just cover Drupal-related Javascript topics.
One change from Drupal 7 to Drupal 8, is that jQuery is no longer automatically loaded. This means jQuery must be manually pulled in as a dependency. There are examples of that below.

Adding Javascript Libraries

Theme and module Javascript should be loaded in using asset libraries (i.e. *.libraries.yml files where * is the name of the theme or module).

Local Javascript Libraries

Suppose you have a theme named mytheme, which needs to include the following Javascript files:
fancy-ui-tabs.js
fancy-ui-accordion.js
fancy-ui-tables.js (dependent on underscore and jQuery)
It would follow that you would create mytheme.libraries.yml with the following contents:
fancy-ui:
  version: 1.x
  js:
    js/fancy-tabs.js: {}
    js/fancy-accordion.js: {}
fancy-ui-tables:
  version: 1.x
  js:
    js/fancy-tables.js: {}
  dependencies:
    - core/underscore
    - core/jquery

External Javascript Libraries

Though it can be problematic for performance and security reasons, there are times when you will need to load external Javascript into your site.
For example loading AngularJS via a CDN, from Adding stylesheets (CSS) and JavaScript (JS) to a Drupal 8 theme:
angular.angularjs:
  remote: https://github.com/angular
  version: 1.4.4
  license:
    name: MIT
    url: https://github.com/angular/angular.js/blob/master/LICENSE
    gpl-compatible: true
  js:
    https://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.min.js: { type: external, minified: true }

Attaching Javascript

Once libraries have been defined, they need to be attached where they are needed.

Attaching to All Pages

To attach Javascript to all pages:
Under the libraries: section of mytheme.info.yml:
libraries:
  - 'mytheme/global-styling'
  - 'mytheme/bootstrap-scripts'
  - 'mytheme/fancy-ui'

Attaching to a Subset of Pages

You can use hooks to add conditionally.
For example, to only load on nodes (skipping other entities), add the following function to your mytheme.theme file.
function mytheme_preprocess_node(&$variables) {
  $variables['#attached']['library'][] = 'mytheme/fancy-tables';
}
Or if you only want to load on the maintenance page:
function mytheme_preprocess_maintenance_page(&$variables) {
  $variables['#attached']['library'][] = 'mytheme/fancy-tables';
}

Drupal.behaviors

Instead of using $(document).ready(function() {}), as is common in jQuery development, it is better to make use of Drupal.behaviors as it will ensure code runs on normal page loads, ajax calls and inside BigPipe.
To enable Drupal.behaviors you must add core/drupal as a Javascript dependency in your theme/module.
my-js-lib:
  version: 1.x
  js:
    js/my-js-lib.js: {}
  dependencies:
    - core/drupal
Example from Javascript API Overview:
Drupal.behaviors.myBehavior = {
  attach: function (context, settings) {
    // Using once() to apply the myCustomBehaviour effect when you want to do just run one function.
    $(context).find('input.myCustomBehavior').once('myCustomBehavior').addClass('processed');

    // Using once() with more complexity.
    $(context).find('input.myCustom').once('mySecondBehavior').each(function () {
      if ($(this).visible()) {
          $(this).css('background', 'green');
      }
      else {
        $(this).css('background', 'yellow').show();
      }
    });
  }
};
attach() is called once the DOM has loaded for all Drupal.behaviors properties, both on the initial page load, and any subsequent ajax calls.

Closures

Since Drupal's implementation of jQuery uses jQuery.noConflict(), it is also considered good practice to wrap your custom Drupal javascript inside of a closure like this:
(function ($, Drupal) {
  Drupal.behaviors.myModuleBehavior = {
    ...
  };
})(jQuery, Drupal);

Translating Strings in Javascript

When necessary, string translation can be performed in Javascript using Drupal.t():
var translatedString = Drupal.t('This is a string about @subject that needs to be translated', {@subject: 'Javascript in Drupal'});
Distinguish between plural and singular translations in Javascript using Drupal.formatPlural():
var typeVar = 'list';
var countingString = Drupal.formatPlural(count, 'I have 1 @type item', 'I have @count @type items', {@type: typeVar});
^ Note: @count is a special placeholder and does need to be defined in your variable array, like @type does. Additionally @count should ever be used in the singular string, only the plural.

Preventing Cross-site Scripting (XSS)

Any user-provided input that has not been properly sanitized previously via Twig or PHP should be passed through Drupal.checkPlain() in JavaScript.

Strict Mode

ECMAScript 5's strict mode is a way to opt in to a restricted variant of JavaScript, thereby implicitly opting-out of "sloppy mode". Strict mode isn't just a subset: it intentionally has different semantics from normal code. Browsers not supporting strict mode will run strict mode code with different behavior from browsers that do, so don't rely on strict mode without feature-testing for support for the relevant aspects of strict mode. Strict mode code and non-strict mode code can coexist, so scripts can opt into strict mode incrementally.
Strict mode makes several changes to normal JavaScript semantics:
  1. Eliminates some JavaScript silent errors by changing them to throw errors.
  2. Fixes mistakes that make it difficult for JavaScript engines to perform optimizations: strict mode code can sometimes be made to run faster than identical code that's not strict mode.
  3. Prohibits some syntax likely to be defined in future versions of ECMAScript.
To place javascript in strict mode add 'use strict'; to the top of the document, closure, or function. For example:
(function ($, Drupal) {
  'use strict';

  Drupal.behaviors.myModuleBehavior = {
    ...
  };
})(jQuery, Drupal);

Strict Mode Restrictions

Language elementRestrictionErrorExample
VariableUsing a variable without declaring it.SCRIPT5042: Variable undefined in strict modetestvar = 4;
Read-only propertyWriting to a read-only property.SCRIPT5045: Assignment to read-only properties is not allowed in strict modevar testObj = Object.defineProperties({}, { prop1: { value: 10, writable: false // by default }, prop2: { get: function () { } } }); testObj.prop1 = 20; testObj.prop2 = 30;
Non-extensible propertyAdding a property to an object whose extensible attribute is set to false.SCRIPT5046: Cannot create property for a non-extensible objectvar testObj = new Object(); Object.preventExtensions(testObj); testObj.name = "Bob";
deleteDeleting a variable, a function, or an argument. Deleting a property whose configurable attribute is set to false.SCRIPT1045: Calling delete on is not allowed in strict modevar testvar = 15; function testFunc() {}; delete testvar; delete testFunc; Object.defineProperty(testObj, "testvar", { value: 10, configurable: false }); delete testObj.testvar;
Duplicating a propertyDefining a property more than once in an object literal.SCRIPT1046: Multiple definitions of a property not allowed in strict modevar testObj = { prop1: 10, prop2: 15, prop1: 20 };
Duplicating a parameter nameUsing a parameter name more than once in a function.SCRIPT1038: Duplicate formal parameter names not allowed in strict modefunction testFunc(param1, param1) { return 1; };
Future reserved keywordsUsing a future reserved keyword as a variable or function name.SCRIPT1050: The use of a future reserved word for an identifier is invalid. The identifier name is reserved in strict mode.implement
interface
package
private
protected
public
static
yield
OctalsAssigning an octal value to a numeric literal, or attempting to use an escape on an octal value.SCRIPT1039: Octal numeric literals and escape characters not allowed in strict modevar testoctal = 010;
var testescape = \010;
thisThe value of this is not converted to the global object when it is null or undefined.function testFunc() { return this; } var testvar = testFunc();

In non-strict mode, the value of testvar is the global object, but in strict mode the value is undefined.
eval as an identifierThe string "eval" cannot be used as an identifier (variable or function name, parameter name, and so on).var eval = 10;
Function declared inside a statement or a blockYou cannot declare a function inside a statement or a block.SCRIPT1047: In strict mode, function declarations cannot be nested inside a statement or block. They may only appear at the top level or directly inside a function body.var arr = [1, 2, 3, 4, 5]; var index = null; for (index in arr) { function myFunc() {}; }
Variable declared inside an eval functionIf a variable is declared inside an eval function, it cannot be used outside that function.SCRIPT1041: Invalid usage of 'eval' in strict modeeval("var testvar = 10"); testvar = 15;

Indirect evaluation is possible, but you still cannot use a variable declared outside the eval function.

var indirectEval = eval; indirectEval("var testvar = 10;"); document.write(testVar);

This code causes an error SCRIPT5009: 'testVar' is undefined.
Arguments as an identifierThe string "arguments" cannot be used as an identifier (variable or function name, parameter name, and so on).SCRIPT1042: Invalid usage of 'arguments' in strict modevar arguments = 10;
arguments inside a functionYou cannot change the values of members of the local arguments object.function testArgs(oneArg) { arguments[0] = 20; }

In non-strict mode, you can change the value of the oneArg parameter by changing the value of arguments[0], so that the value of both oneArgand arguments[0] is 20. In strict mode, changing the value of arguments[0] does not affect the value of oneArg, because the arguments object is merely a local copy.
arguments.calleeNot allowed.function (testInt) { if (testInt-- == 0) return; arguments.callee(testInt--); }
withNot allowed.SCRIPT1037: 'with' statements are not allowed in strict modewith (Math){ x = cos(3); y = tan(7); }


git

Git is a version control tool used by Drupal.
It is recommended you learn git separately, but here are some commonly used commands:

Basic git commands

  • git add - Adds files to staging area.
  • git commit - Commits files to repo.
    • -a: Adds all unstaged files.
    • -m: Sets commit message from command line.
    • --amend: Amends the most recent commit message.
  • git push - Pushes local repo to a remote repo.
  • git pull - Incorporates changes from a remote repository into the current branch.
  • git clone - Clones a remote repo to your local system.
  • git checkout - Switch to another branch
    • -b: Create a new branch prior to switching
  • git rebase - Changes the history of a commit relative to another commit.
  • git merge - Merges one branch into another.
  • git reset - Resets HEAD to specified state.
  • git clean - Removes unstaged files from working tree.
  • git revert - Reverts changes made in a commit.
  • git log - Show commit logs.

Advanced git commands

  • git cherry-pick - Applies changes introduced by another commit (useful across branches).
  • git bisect - Finds commit that introduced bug/functionality change using binary search which is O(lg n).
  • git grep - Find lines/files matching pattern within repo.
  • git reflog - Manage reflog information.
  • git gc - Performs garbage collection on local repository.


Site Building



Content Types

Content types typically contain the main content of a page on a Drupal site.

Content Entities

A content entity (or more commonly, entity) is an item of content data, which can consist of text, HTML markup, images, attached files, and other data that is intended to be displayed to site visitors. Content entities can be defined by the core software or by modules.
Content entities are grouped into entity types, which have different purposes and are displayed in very different ways on the site. Most entity types are also divided into entity sub-types, which are divisions within an entity type to allow for smaller variations in how the entities are used and displayed.

Adding a Content Type

  1. Navigate to Structure -> Content Types. The Content types page appears showing all the available types of content.
  2. Click Add Content TypeAdd Content Type

Field Types

GeneralNumberReferenceText
BooleanList (float)ContentList (Text)
CommentsList (integer)FileText (formatted)
DateNumber (decimal)ImageText (formatted, long)
EmailNumber (float)Taxonomy TermText (formatted, long, with summary)
LinkNumber (integer)UserText (plain)
TimestampOther...Text (plain, long)

Adding Fields to a Content Type

  1. Navigate to Structure -> Content Types. The Content types page appears showing all the available types of content.
  2. Click Manage Fields link in the dropdown for the Operations column.
  3. Click Add fieldAdd field



Display Modes

Display modes exist to provide different presentations of Content Entities for either viewing or editing. The two types of display modes are "view modes" and "form modes." Both of these display mode types—view modes and form modes—are examples of "configuration entities."
uuid: 15dc7aa9-13fd-4412-9c06-06d09f915d08
langcode: en
status: false
dependencies:
  module:
    - node
id: node.full
label: 'Full content'
targetEntityType: node
cache: true
reference: core.entity_view_mode.node.full.yml
The main property to take note of is the "targetEntityType" property. Each display mode (view mode or form mode) is associated with one, and only one, type of Content Entity.

View Modes

View modes exist to allow Drupal site building tools like Entity Reference fields to request a given entity be rendered in a certain way.
To see the list of View Modes navigate to Structure -> Display modes -> View modesView Modes List
To update the available View Modes for a specific content type navigate to Structure -> Content types -> Edit -> Manage display -> Custom Display SettingsAvailable View Modes

Form Modes

Form modes allow for multiple sets of field widget orderings and customizations, just as view modes allow for different orderings and customization of field formatters.
Unlike view modes (which fall back to the default view display if view display does not exist for a given view mode) form modes will not use the ‘default’ operation by default.
To see the list of Form Modes navigate to Structure -> Display modes -> Form modesForm Modes List



Taxonomies

According to Drupal.org - Taxonomy:
Taxonomy is used to classify website content. One common example of taxonomy is the tags used to classify or categorize posts in a blog website; the farmers market website could use an ingredients taxonomy to classify recipes. Individual taxonomy items are known as terms and a set of terms is known as a vocabulary
Technically, taxonomy terms are an entity type and the entity subtypes are the vocabularies. Like other entities, taxonomy terms can have fields attached; for instance, you could set up an image field to contain an icon for each term.
An individual vocabulary can organize its terms in a hierarchy, or it could be flat.
Taxonomy terms are normally attached as reference fields to other content entities to provide categorization of content.

Adding a New Vocabulary

To add a new vocabulary to your Taxonomy list:
Navigate to Structure -> Taxonomy -> Add vocabularyAdd new Taxonomy vocabulary

Adding a Term Reference

  1. Navigate to Structure -> Content types -> Manage fields -> Add field.
  2. Pick Taxonomy term from the dropdown and provide a label.
  3. Click Save and ContinueAdd new term reference
  4. Select the type of item to reference. Taxonomy reference.
  5. Click Save field settings.
  6. Fill out the necessary fields. Add new Taxonomy term - Save Settings
  7. Click Save settings.

Adding New Terms to Your Vocabulary

To add new terms to your Vocabulary:
Navigate to Structure -> Taxonomy -> List terms -> Add termAdd new Taxonomy term

Free Tagging

Allows new terms to be created right on the content editing form.
To enable the ability to add terms while editing content:
  1. Navigate to Structure -> Content types -> Manage fields.
  2. Click Edit for your Term Reference field.
  3. Check Create referenced entities if they don't already exist.
  4. Using the dropdown, choose the vocabulary your new terms will be saved to. Free tagging

Blocks

Blocks are individual pieces of your site’s web page layout. They are placed inside the regions of your theme, and can be created, removed, and rearranged in the Block layout (admin/structure/block) administration page. Examples of blocks include the Who’s online listing, the main navigation menu, and the breadcrumb trail. The main page content is also a block.
Some modules make new blocks available for placement on your site. For example, when the core Search module is installed and configured, it provides a block that contains a search form. You may also create and place your own custom blocks.
Each block has its own configuration settings, which allow you to select which pages of your site will display the block. It is even possible to place multiple copies of a block, each with its own separate configuration and visibility rules.

Block Management

Blocks can be found at Structure -> Block layout.
Block List
You can configure a specific block by clicking the Configure button next to that block.
Block Configure

Block Visibility

You can configure a blocks visibility settings (i.e. where they will and won't show up), based on:
  1. Language (If Multilingual is enabled)
    Block Language
  2. Content Type
    Block Content Types
  3. Page
    Block Pages
  4. User Role
    Block Roles

Block Placement

You can either place a specific block into a region by configuring the block, or by clicking the "Place block" button for a particular region on the Block layout page.
Block Placement

Menus

Menus are a collection of links (menu items) used to navigate a website. The core Menu UI module provides an interface to control and customize the menu system. Menus are primarily displayed as a hierarchical list of links. By default, new menu items are placed inside a built-in menu labeled Main navigation, but administrators can also create custom menus.
The core Standard installation profile contains five menus:
Main navigation
Links to sections intended for site visitors. They are usually created by site administrators.
Administration
  • Links to administrative tasks. This menu mainly contains links supplied by modules on your site.
User account menu
  • Links to tasks associated with the user account such as My account and Log out.
Footer
  • Links to important pages within the site intended for the footer. They are usually created by site administrators.
Tools
  • Links to tasks necessary for site visitors. Some modules feature their links here.

Menu Management

You can see all menus in your system by going to Structure -> Menus.
Menus List
You can add a new menu by going to Structure -> Menus -> AddMenus Add
You can edit an existing menu by clicking the Edit menu button next to the respective menu you wish to manipulate.
Menus Edit
You can edit an existing menu link by clicking Edit next to the particular menu item you wish to modify on the menu edit page. Menu Link Edit

Menu Placement

Menus are exposed in Drupal 8 as block, so you can use standard block placement to insert a menu onto your site.
Menu Placement
See Blocks for more information about blocks in Drupal.

Views

There is a lot of functionality around views. It is recommended you read through the official Views Module documentation.
This guide will just cover the bare functionality.

What Are Views?

Using the Views module, you can fetch content from the database of your site and present it to the user as lists, posts, galleries, tables, maps, graphs, menu items, blocks, reports, forum posts etc. Different content types including nodes, users, and other bundles can be displayed.
Views UI, a submodule within Views, provides a graphical interface underneath which lies a powerful SQL query builder that can access virtually any information in your database and display it in any format.
Different displays can present the query results as pages with fixed URLs on your site (or URLs accepting arguments), blocks, feeds, or panel panes.

Existing Views

If you enable the Views UI module you can see all views in your system by going to Structure -> Views.
Views List
You can edit or delete a view by clicking the respective link for the view you wish to manipulate.
By editing a view, you can see the various components of a view:
Views Edit

Adding a New View

  • You can add a new view by going into Structure -> Views -> Add.
    Views Add
    Views Add

Displays

  • The various displays inside a view:
    Views Display
    You can add additional displays clicking the Add button.
  • You can also use the views display menu for more options:
    Views Display Menu
  • A display's title can be set here:
    Views Display Title
  • Additionally each display may have settings specific to the display type:
    • Page Display:
      Views Display Settings - Page Display
    • Rest Export Display Settings:
      Views Display Settings - REST Export

Format

  • Depending on the format of your view, your view output can vary widely. Some include the ability to output specific fields, and others include options to output entities themselves. You will find the format here:
    Views Format
    Views Format - 2
  • By clicking the current format name you can change the format being used: Views Format Options
  • Depending on your settings, you may have the ability to add fields for display: Views Fields
  • By clicking the Add button you can choose from a large list of all available fields. (Note: You can add a field to just the particular display you are on, or all displays).
    Views Fields Add

Filtering and Sorting

  • You can use certain fields and other criteria for filtering and sorting your results. (Note: You can "expose" filters and sorting criteria in a view, to allow users to specify these values dynamically)
    Views Filter
    Views Sort
  • By clicking the Add button you can choose from a large list of all available fields, filters and sorting criteria. (Note: You can add a field to just the particular display you are on, or all displays).
    Views Filter - Add

Headers/Footers/No Results

  • You can specify specific content for the views header, footer and also define the behavior when a view returns no results:
    Views Header/Footer/No Results

Pager

  • You can set pagination settings for your view results.
    Views Filter - Pager

Language

  • If your site is configured for Multilingual support, you can specify language-specific settings for your results.

Advanced

The advanced section provides functionality useful in more advanced use cases.
Views Advanced

Contextual Filters

Views is a highly flexible module to start with, but the contextual filters increase the use cases for the module by an order of magnitude. Contextual filters work similarly to regular filters, but there is one important difference. Instead of setting a filter value manually, the value is fetched from variables sent programmatically to the view. A regular filter could give you all nodes written by a specified user. A contextual filter for a node author would be able to display all nodes written by the currently viewed user, or the same user who wrote the currently viewed node. The concept is that contextual filters prepare a view for filtering, but the filter value is not yet determined. When the view is eventually called, it is also provided with data used to complete the contextual filters.

Relationships

You can use Relationships to make connections from your view results to other entities. This is commonly done through entity reference fields. By making these connections you expose additional fields and information to views.

Exposed Form

Advanced settings for a view's exposed filters.

Other

  • Machine name - The machine name for this specific display
  • Administrative comment - Leave comments for admins related to this particular view or display
  • Use AJAX - Turns on AJAX processing for filters and pagination
  • Hide attachments in summary - Hide attachments when displaying argument summary
  • Contextual links - Whether not to show contextual menu for this view
  • Use aggregation - Aggregate results together
  • Query settings - Advanced database options
  • Caching - View cache settings
  • CSS class - Add CSS classes to your view



Configuration Management

The configuration API provides a central place for modules to store configuration data. This data can be simple configuration like your site name, or more complex information managed with configuration entities, such as views and content types.
Configuration is a place to store information that you would want to synchronize from development to production. This information is often created during site building and is not typically generated by regular users during normal site operation.
Configuration management in D8 works similar to how Features module did in D7, but now ships out as part of core.
By default configuration data is stored in the config database table. The configuration management system built into core allows you to import and export these configuration settings across multiple environments and formats.

Exporting Configurations

Exporting Full Site Configurations

  1. Make a configuration change to your system, such as the name of your site.
  2. Navigate to Configuration -> Development -> Configuration Synchronization -> Export
  3. Click Export Export Full Site Configuration
  4. Your browser will download an exported file configuration tarball (e.g. config-localhost-8888-2017-04-01-04-10.tar.gz)

Exporting Single Items

  1. Make a configuration change to your system, such as the name of your site.
  2. Navigate to Configuration -> Development -> Configuration Synchronization -> Export -> Single item
  3. Select the type and name of the config item you wish to export. Export Item
  4. You can now copy and paste this configuration elsewhere for future reference.

Viewing Configuration Changes

  1. Make a configuration change to your system for something that was previously exported, such as the name of your site.
  2. Navigate to Configuration -> Development -> Configuration Synchronization Configuration Synchronization
  3. Click View Differences Configuration Differences
  • The Active column indicates the current setting in your site.
  • The Staged column indicates the value from the previous exportation.

Importing Configurations

Importing Full Site Configurations

  1. Obtain a previous export tarball (See Exporting Full Site Configuration above)
  2. Navigate to Configuration -> Development -> Configuration Synchronization -> Import
  3. Click Import Import Full Site Configuration
  4. After reviewing your changes, click Import AllImport Full Site Configuration - Review

Importing Single Items

  1. Obtain YAML from a previous export.
  2. Navigate to Configuration -> Development -> Configuration Synchronization -> Import -> Single item
  3. Select the type and name of the config item you wish to import and press Import Import Item
  4. Click Confirm Import Item

Drush

View configuration settings using drush:
drush config-get system.site
drush config-get system.site name
drush config-get system.site mail
# or
drush cget system.site
drush cget system.site name
drush cget system.site mail
Set configuration settings using drush:
drush config-set system.site name 'My Company Website'
drush config-set system.site mail 'joe.rodgers@mycompany.com'
# or
drush cset system.site name 'My Company Website'
drush cset system.site mail 'joe.rodgers@mycompany.com'
To export configurations using drush:
drush config-export
# or
drush cex
^ This is similar to regenerating features in D7.
To import configurations using drush:
drush config-import
# or
drush cim
^ This is similar to reverting features in D7.

Configuration Storage

You can alter the storage location of your configuration in your settings.php file (or comparable file in your system):
<?php
/**
 * Location of the site configuration files.
 *
 * The $config_directories array specifies the location of file system
 * directories used for configuration data. On install, the "sync" directory is
 * created. This is used for configuration imports. The "active" directory is
 * not created by default since the default storage for active configuration is
 * the database rather than the file system. (This can be changed. See "Active
 * configuration settings" below).
 *
 * The default location for the "sync" directory is inside a randomly-named
 * directory in the public files path. The setting below allows you to override
 * the "sync" location.
 *
 * If you use files for the "active" configuration, you can tell the
 * Configuration system where this directory is located by adding an entry with
 * array key CONFIG_ACTIVE_DIRECTORY.
 *
 * Example:
 * @code
 *   $config_directories = array(
 *     CONFIG_SYNC_DIRECTORY => '/directory/outside/webroot',
 *   );
 * @endcode
 */


Multilingual

The Drupal 8 Multilingual Initiative focused on making multilingual support an integral part of core functionality. You now have the option of selecting your default language right during the installation process.
Multilingual - Installation
When you select a language other than English, Drupal will automatically enable the necessary multilingual modules (i.e. Language Module and Interface Translation Module), and download the latest translations from localize.drupal.org.
Multilingual - Installation
Where Drupal 7 required a very large number of modules to handle distinct aspects of multilingual support, Drupal 8 has most of these features wrapped into just 4 modules to help create a better user experience:
  1. Language Module
  2. Interface Translation Module
  3. Content Translation Module
  4. Configuration Translation Module

Language Module

(machine name: language)
The base module needed for any non-English or multi-lingual site. Allows users to configure languages and how page languages are chosen, and apply languages to content.
This module provides a lot of functionality out of the box:

Support for many languages (and always improving)

Language support is always improving. You can keep track and contribute to the localization of Drupal at localize.drupal.org.
To manage language support go to Configuration -> Regional and Language -> Languages
Languages

Everything can have a language

Drupal 8 has made all content easily translatable. This includes nodes, users, views, blocks, menus and many other entity-based components.
To specify language options for specific content types: Structure -> Content Types -> (SOME CONTENT TYPE) -> Edit -> Language Settings Content Types
To specify language options for specific blocks: Structure -> Block Layout -> (SOME BLOCK) -> Configure -> Language Blocks
To specify language options for specific menus: Structure -> Menus -> (SOME MENU) -> Edit Menu -> Menu Language Blocks
To specify language options for specific users: People -> (SOME USER) -> Edit -> Language Settings Blocks

Two special languages

  • Language Not Specified (const LANGUAGE_NOT_SPECIFIED = 'und') - Used when multilingual options are available, but unused for a particular piece of content. This is comparable to LANGUAGE_NONE in Drupal 7.
  • Language Not Applicable (const LANGUAGE_NOT_APPLICABLE = 'zxx') - Used when language options do not apply to a particular piece of content (e.g. an image)

Language negotiation

There are multiple methods to detect which language should be used. You can opt to use as many methods as you want to evaluate a user's language preference.
The options are available, from Enable Language Negotiation:
  • URL - Determine the language from the URL (Path prefix or Domain).
  • Session - Determine the language from a request/session parameter.
  • User - Follow the user's language preference.
  • Browser - Determine the language from the browser's language settings.
  • Default language - Use the default site language (English).
If multiple methods are selected, Drupal will attempt methods based on their sort order and fallback to the next method if it cannot determine the language based on a particular method.
To change methods and the fallback order go to Configuration -> Regional and Language -> Languages -> Language Detection and Selection
Language Negotiation

Configurable Browser Language Detection

Browsers use different language codes to refer to the same languages. For example zh-twzh-hk and zh-mo may all refer to Chinese Traditional.
Drupal will prepopulate this list based on common browser settings, but this list can be customized at Configuration -> Regional and Language -> Languages -> Language Detection and Selection -> Browser -> Configure Browser Detection

Transliteration

The core/component transliteration classes do basic character-by-character transliteration using a database of generic character transliterations and language-specific overrides, which is OK for basic uses such as creating legal file names and machine names, but not good for transliterating prose (which would require consideration of context, capitalization, etc.).

Interface Translation Module

(machine name: locale)
When enabled, the core Interface Translation ("Locale" in versions before Drupal 8) module allows you to present your Drupal site in a language other than the default (English).
You can use it to set up a multilingual web site or to replace the elements of the interface text with text which has been customized for your site. Whenever the Interface Translation module encounters text, it tries to translate it into the currently selected language. If a translation is not available, the string is remembered, so you can look up untranslated strings easily.
To translate specific UI strings go to: Configuration -> Regional and Language -> Languages -> User Interface Translation and then selecting your language and specifying translation values for each particular string.
Interface Translation Settings
To configure your UI translation settings go to: Configuration -> Regional and Language -> Languages -> User Interface Translation -> Settings
Interface Translation Settings
From here you can either configure automatic update language synchronization from localize.drupal.org, or click the Check Updates Now link, to pull down the latest translation strings for your UI.

Content Translation Module

(machine name: content_translation)
Allows users to translate content entities. Allows you to translate your site content, including pages, taxonomy terms, blocks, etc., into different languages.

Default translation settings

Configuration -> Regional and Language -> Content language and translationContent Translation
Check the "Translatable" checkbox next to each item you want to translate.

Translating a node

While viewing a node of a content type with translation enabled, you should now see a Translate tab. Translate Tab
Click Add next to the language you wish to translate. Content Types
Specify the translated node content and then save. Content Types

Configuration Translation Module

(machine name: config_translation)
Provides a translation interface for configuration. Allows you to translate text that is part of the configuration, such as field labels, the text used in Views, etc.
To translate configuration settings go to Configuration -> Regional and Language -> Configuration translationConfiguration translation list
Find a configuration setting you wish to translate and click the Translate button. (Note: If you see a button that says Listinstead of Translate) this means you're in a parent group and must click through to get to more specific configuration settings. Configuration translation list
When you click Translate on a particular item, you should see the option to either add or edit an existing translation. Configuration translation add
Edit the particular settings you wish to update and then click the Save Translation button. Configuration translation add
See Configuration Management for more information on managing configurations in Drupal.

Web Services

The RESTful Web Services API is new in Drupal 8. Expose entities as REST resources either to build a decoupled Drupal site, to let a native mobile iOS/Android app talk consume/feed a Drupal site, or to integrate with some web service.

Modules

The following Web Services modules are available in core:

REST Request Fundamentals

Safe HTTP Methods (read-only):

  • GET - Request data from a URI
  • HEAD - Retrieve headers from a URI
  • OPTIONS - Request available communication options
  • TRACE - Echoes back request sent to server

Unsafe HTTP Methods (write)

  • CONNECT - Opens a raw connection to a host through a proxy chain
  • DELETE - Requests that a server delete the resource at URI
  • PATCH - Request changes on a URI
  • POST - Submit data to a URI
  • PUT - Request submitted data be stored under a URI (currently not supported)
All unsafe methods require X-CSRF-Token request header, which can be retrieved at /rest/session/token.

Serialization Formats

  1. Always specify the ?_format query argument, e.g. http://example.com/node/1?_format=json
  2. When sending a request body containing data in that format, specify the Content-Type request header. This is the case for POST and PATCH.

Authentication

  • basic - The quickest way to get started is to use basic HTTP Authentication. Enable the Basic Auth module found in core, then send your drupal username and password using HTTP Authorization Headers
  • cookie - Use the cookie granted to an authenticated user.
You can also use third-party modules to provide support for other authentication such as OAuth.

REST Configuration

Note: These instructions are for Drupal 8.2 and later. See RESTful Web Services API overview for information on configuring Drupal 8.0 & 8.1.

Configuration Methods

Configurations are managed with YAML but can setup via REST UI module.
Each REST resource has a \Drupal\rest\RestResourceConfigInterface config entity that corresponds to a @RestResource plugin. Without such a config entity, the REST resource plugin will not be available for use.
There are two methods for configuring resources:
  • granularity: method: Set serialization formats and authentication per HTTP method.
  • granularity: resource: Set serialization formats and authentication per resource.
Examples:
...
granularity: method
configuration:
  GET:
    supported_formats:
      - json
    supported_auth:
      - basic_auth
      - cookie
...
...
granularity: resource
configuration:
  methods:
    - GET
    ...
  formats:
    - json
    ...
  authentication:
    - basic_auth
...

Examples

Using lessons learned in 2.7 - Configuration Management, import the following configuration, specifying REST resource configuration as the configuration type:
id: entity.node
plugin_id: 'entity:node'
granularity: resource
configuration:
  methods:
    - GET
    - POST
    - PATCH
    - DELETE
  formats:
    - json
    - hal_json
    - xml
  authentication:
    - basic_auth
    - cookie
The above configuration supports GET/POST/PATCH/DELETE requests.
Since this creates a generic endpoint, this data can now be consumed by any number of languages, frameworks and applications. The following examples illustrate a few different options:

GET

Assuming you have a node previously setup with nid of 1, you can test this by navigating to /node/1?_format=json in your browser. If setup correctly, you should see your node represented by JSON instead of HTML.
For more detailed examples, see GET for reading content entities example.

POST

x_csrf_token=$(curl --silent http://localhost:8888/rest/session/token)

curl --include \
  --request POST \
  --user admin:password \
  --header 'Content-type: application/hal+json' \
  --header "X-CSRF-Token: $x_csrf_token" \
  http://localhost:8888/entity/node?_format=hal_json \
  --data-binary '{"_links":{"type":{"href":"http://localhost:8888/rest/type/node/article"}},"title":[{"value":"My Node Title"}],"type":[{"target_id":"article"}]}'
Notes:
  • This example requires the HAL module
  • For security reasons it is considered bad practice to type passwords directly into your terminal. More secure methods of authentication should be considered.
For more detailed examples, see POST for creating content entities example.

PATCH

function getCsrfToken(callback) {
  jQuery
    .get(Drupal.url('rest/session/token'))
    .done(function (data) {
      var csrfToken = data;
      callback(csrfToken);
    });
}

function patchNode(csrfToken, node) {
  jQuery.ajax({
    url: 'http://localhost:8888/node/1?_format=hal_json',
    method: 'PATCH',
    headers: {
      'Content-Type': 'application/hal+json',
      'X-CSRF-Token': csrfToken
    },
    data: JSON.stringify(node),
    success: function (node) {
      console.log(node);
    }
  });
}

var newNode = {
  _links: {
    type: {
      href: 'http://localhost:8888/rest/type/node/article'
    }
  },
  type: {
    target_id: 'article'
  },
  title: {
    value: 'This is my brand new title'
  }
};

getCsrfToken(function (csrfToken) {
  patchNode(csrfToken, newNode);
});
Notes:
  • This example requires the HAL module
  • This example assumed cookie-based authentication, which means you need to be running under the same domain name.
For more detailed examples, see PATCH for updating content entities example.

DELETE

<?php
$response = \Drupal::httpClient()
  ->delete('http://localhost:8888/node/1?_format=json', [
    'auth' => ['admin', 'password'],
    'body' => '',
    'headers' => [
      'X-CSRF-Token' => $x_csrf_token
    ],
  ]);
?>
Notes:
  • This example assumes you already have the $x_csrf_token value to the value from /rest/session/token.
For more detailed examples, see DELETE for deleting content entities example

Exposing Views via Web Services

To expose a view via Web Services:
  1. Edit your view.
  2. Under Displays click + Add and select REST exportWeb Services - Views 1
  3. Under Path Settings set a path for your export. Web Services - Views 2
  4. You can adjust various settings in regards to format and fields to display as you would with any other view.
  5. Once you are finished, save your view
  6. Navigate to the path specified above in your browser. If everything went as expected, you should see your via in your specified format: Web Services - Views 3

Front End Development (Theming)



Creating Themes and Subthemes

In Drupal 8 you can create base themes and subthemes. A base theme provides some set of predefined styles and functionality that a frontend developer can base a subtheme on. Any theme can be used as a base theme, even if it is a subtheme of some other theme.

Core Themes

Drupal 8 comes with five preloaded themes, located in core/themes/.
  1. Stable: Default base theme for all other themes unless otherwise specified. It is a minimalist theme, that only introduces essential CSS and functionality.
  2. Classy: Base theme that comes prepackaged with "sensible" default markup and css classes.
  3. Bartik: Based on Classy. The default frontend Drupal theme. It is simple and responsive.
  4. Seven: Based on Classy. The default admin Drupal theme.
  5. Stark: Is not based on any other theme. It is intentionally styleless to demonstrate default Drupal HTML, CSS and Javacript from core and contrib modules.

Choosing a Base Theme

Choosing a base theme is a big decision when creating a new Drupal theme as it lays the framework for the way you will be building your frontend. From a D8 perspective, Stable and Classy are the two standard base themes provided out of the box, although you could technically use BartikSeven and Stark as a base theme if you really wanted to.
The reason Drupal 8 provides two base themes is to appeal to two different groups of developers:
  • "Sensible 2/3" developers who want sensible markup and default classes to apply CSS with minimal overrides.
  • "Clean 1/3" developers who want a minimalist theme that doesn't place unnecessary markup and css upon themers.
As a compromise, Stable was established for the minimalists, and Classy was for those wanting sensible markup and classes.
See Results of Drupalcon Austin's Consensus Banana for more information about that decision.
But these are only two out of a theoretically infinite number of base themes you can choose from, including a custom base theme that is shared by all of your different projects.
You can also opt out of using a base theme (see Stark theme), but just recognize that by doing so you are no longer guaranteeing backwards compatibility when core functionality changes.

File Structure

Custom and third-party themes should be installed in /themes/{themename}.
Inside each theme it is recommended to have cssjs and images directories.

{themename}.info.yml

Drupal automatically searches the themes directory looking for {themename}.info.yml. This file provides information about your theme to Drupal.
For example - substable.info.yml:
name: Substable
type: theme
description: 'A stable subtheme'
core: 8.x
libraries:
  - substable/global-styling
  - substable/global-scripts
base theme: stable
regions:
  header: Header
  content: Content
  sidebar_left: 'Sidebar - Left'
  sidebar_right: 'Sidebar - Right'
  footer: Footer

Theme Keys

Here is a list of available theme keys from Defining a theme with an .info.yml file:
  • name (required) - The human-readable name. This will appear on the "Appearance" page where the theme is activated.
  • type (required) - Indicates the type of extension, i.e., "module", "theme", or "profile". For themes this should always be set to "theme".
  • description (optional) - The description, displayed on the "Appearance" page.
  • package (optional) - Specifies a "package" that allows you to group themes together.
  • core (required) - Specifies the version of Drupal core that the theme is compatible with.
  • php (optional) - The minimum version of PHP required. Defaults to value of DRUPAL_MINIMUM_PHP constant.
  • version (optional) - Specifies a version. For themes hosted on drupal.org, the version number will be filled in by the packaging script. Do not specify it manually, but leave out the version line entirely.
  • libraries (optional) - A list of libraries (which can contain both CSS and JavaScript assets) to add to all pages where the theme is active.
  • libraries-override (optional) - A collection of libraries and assets to override.
  • base theme (recommended) - A theme can inherit the resources from another theme by specifying it as a base theme. It is recommended to use classy or stable (stable is the default if the key is not supplied) – this makes it easier for your theme to inherit future changes in core theming.
  • hidden (optional) - Indicates whether or not to hide the theme from the "Appearance" page so that it cannot be enabled/disabled via the UI.
  • engine (optional) - The theme engine. Defaults to "twig".
  • screenshot (optional) - The path to screenshot relative to the theme's .info.yml file. Screenshots should be 588 pixels wide and 438 pixels high, though they are displayed at a smaller size. By default, Drupal will look for a file named "screenshot.png" in the root of your theme folder and use that as the theme image on the "Appearance" page.
  • regions (optional) - A list of theme regions. (Note that region keys are not preceded by a dash.) A content region is required. Read more about adding regions to a theme.
  • regions_hidden (optional) - A list of inherited regions to remove.
  • features (optional) - A list of features to expose on the theme "Settings" page.
  • stylesheets-remove (deprecated) - A list of stylesheets from other modules or themes to remove from all pages where the theme is active. Each value must be a full path relative to the docroot to resolve ambiguity when more than one file with the same name exists. In cases where the file is part of a library that belongs to a module or theme, a token in the form @module_or_theme_name can be used in place of the full path. Note that when using the token the value must be quoted because "@" is a reserved indicator in YAML. Note: This key is deprecated and will be removed in Drupal 9. In most cases libraries-override should be used.
  • ckeditor_stylesheets (optional) - A list of stylesheets to add to the CKEditor frame.

{themename}.libraries.yml

If you wish to include Javascript and CSS in your theme, you can do so by creating libraries in {themename}.libraries.yml.
For example - substable.libaries.yml:
global-styling:
  version: 1.x
  css:
    theme:
      css/style.css: {}
      css/print.css: { media: print }
global-scripts:
  version: 1.x
  js:
    js/substable.js: {}
  dependencies:
    - core/jquery
Libraries also need to be included in the {themename}.info.yml file. See substable.info.yml example above.
See the Javascript/jQuery section for more information about Javascript and attaching libraries to a subset of pages.

Breakpoint Module

The breakpoints module allows you to predefine breakpoints for use in your responsive design. Breakpoints are defined in a {themename}.breakpoints.yml file.
Here is an example from the bootstrap theme:
bootstrap.screen-xs-max:
  label: screen-xs-max
  mediaQuery: 'all and (max-width: 767px)'
  weight: 1
  multipliers:
    - 1x
bootstrap.screen-sm-min:
  label: screen-sm-min
  mediaQuery: 'all and (min-width: 768px)'
  weight: 1
  multipliers:
    - 1x
bootstrap.screen-sm-max:
  label: screen-sm-max
  mediaQuery: 'all and (max-width: 991px)'
  weight: 1
  multipliers:
    - 1x
bootstrap.screen-md-min:
  label: screen-md-min
  mediaQuery: 'all and (min-width: 992px)'
  weight: 1
  multipliers:
    - 1x
bootstrap.screen-md-max:
  label: screen-md-max
  mediaQuery: 'all and (max-width: 1199px)'
  weight: 1
  multipliers:
    - 1x
bootstrap.screen-lg-min:
  label: screen-lg-min
  mediaQuery: 'all and (min-width: 1200px)'
  weight: 1
  multipliers:
    - 1x
Please note that inputting your CSS breakpoints into your breakpoints.yml file is only necessary when Drupal needs to interact with the breakpoints as in the case of the Responsive Images module.

Breakpoint Keys

  • label - A human readable label for the breakpoint.
  • mediaQuery - Media query text proper, e.g. 'all and (min-width: 851px)'.
  • weight - Positional weight (order) for the breakpoint.
  • multipliers - Supported pixel resolution multipliers.

Breakpoint Groups

Breakpoints can be organized into groups. Modules and themes should use groups to separate out breakpoints that are meant to be used for different purposes, such as breakpoints for layouts or breakpoints for image sizing.
yourtheme.group1.mobile:
  label: narrow
  mediaQuery: ''
  weight: 0
  multipliers:
    - 1x
  group: yourtheme.group1
yourtheme.group1.narrow:
  label: narrow
  mediaQuery: '(min-width: 560px)'
  weight: 0
  multipliers:
    - 1x
    - 2x
  group: yourtheme.group1
yourtheme.group1.wide:
  label: wide
  mediaQuery: '(min-width: 851px)'
  weight: 1
  multipliers:
    - 1x
    - 2x
  group: yourtheme.group1

yourtheme.group2.mobile:
  label: narrow
  mediaQuery: ''
  weight: 0
  multipliers:
    - 1x
  group: yourtheme.group2
yourtheme.group2.narrower:
  label: narrow
  mediaQuery: '(min-width: 400px)'
  weight: 0
  multipliers:
    - 1x
    - 2x
  group: yourtheme.group2
yourtheme.group2.wider:
  label: wide
  mediaQuery: '(min-width: 1001px)'
  weight: 1
  multipliers:
    - 1x
    - 2x
  group: yourtheme.group2
You can also add breakpoints to breakpoint groups defined by other modules or themes, but you must use the full name.
yourmodule.yourtheme.group2.superwide
  label: superwide
  mediaQuery: '(min-width: 1501px)'
  weight: 1
  multipliers:
    - 1x
    - 2x
  group: yourtheme.group2

Adding Regions to a Theme

All regions should be declared in the theme info file. The keys match the machine name and the values match the label for each available region.
For example:
regions:
  header: Header
  content: Content
  sidebar_left: 'Sidebar - Left'
  sidebar_right: 'Sidebar - Right'
  footer: Footer
Then each region can be referenced in your page.html.twig file:
<div class="container">

  {% if page.header %}
    <div class="row">
      <div class="header col-xs-12">
        {{ page.header }}
      </div>
    </div>
  {% endif %}

  <div class="row">

    {% if page.sidebar_left %}
      <div class="sidebar-left col-xs-2">
        {{ page.sidebar_left }}
      </div>
    {% endif %}

    {% if page.sidebar_left and page.sidebar_right %}
      <div class="content col-xs-8">
        {{ page.content }}
      </div>
    {% elseif page.sidebar_left or page.sidebar_right %}
      <div class="content col-xs-10">
        {{ page.content }}
      </div>
    {% else %}
      <div class="content col-xs-12">
        {{ page.content }}
      </div>
    {% endif %}

    {% if page.sidebar_right %}
      <div class="sidebar-right col-xs-2">
        {{ page.sidebar_right }}
      </div>
    {% endif %}

  </div>

  {% if page.footer %}
    <div class="row">
      <div class="footer col-xs-12">
        {{ page.footer }}
      </div>
    </div>
  {% endif %}

</div>
Default regions
If you declare any regions in your theme, even just one, all the default regions will no longer be applied and you assume responsibility for declaring any and all regions you want to use.

Theming Concepts

Drupal 8 introduced a new theming layer that helps reduce complexity for designers and frontend developers. The Mobile Initiative focused on making Drupal mobile-friendly right out of the box by making all themes responsive and implementing numerous frontend performance improvements. The Drupal HTML5 Initiative brought HTML 5 into core and allows for increased frontend functionality and improved accessibility.
Another major change is the introduction of Twig as the default templating engine. See Twig Syntax and Twig Templates for more information about using Twig.

Theme Configuration

All available themes can be found in the Appearance page.
Change Default Theme
You can change the default frontend theme by clicking Set as default next to the theme you wish to activate.

Change Administration Theme
You can change the default admin theme by change the Administration theme dropdown value and clicking the save button.

If a theme hasn't been installed yet, you will need to install to enable it.
Install a Theme
To do so, just click Install or Install and set as default for the theme you wish to enable.

Default themes can also be set in your system.theme.yml configuration file.
For example:
admin: seven
default: bartik

Additional theme settings can be set by clicking Settings next to the theme you wish to change.
Theme Settings


Twig Syntax

Twig is a template engine for PHP and it is part of the Symfony2 framework.
In Drupal 8 Twig replaces PHPTemplate as the default templating engine. One of the results of this change is that all of the theme_* functions and PHPTemplate based *.tpl.php files have been replaced by *.html.twig template files.

Printing Variables and Functions

Twig uses {{ }} syntax to output data.
  • {{ 3 }} will output the integer 3.
  • {{ 'xyz' }} will output the string xyz
  • {{ myvar }} will output the variable myvar
  • {{ someFunction }} will output the results of someFunction()
  • {{ someFunction(foo, bar) }} will out put the results of someFunction(foo, bar)

Arrays and Objects

Array items and object properties/methods can be accessed using a dot (.):
{{ foo.0 }}
{{ foo.bar }}
{{ foo.method }}
{{ foo.method(baz) }}
This allows themers to not worry about variable types, and just output the data.
Array items can also be accessed using the subscript syntax ([]):
{{ foo[0] }}
{{ foo['bar'] }}
For convenience's sake foo.bar does the following things on the PHP layer:
  • check if foo is an array and bar a valid element; if not, and if foo is an object, check that bar is a valid property;
  • if not, and if foo is an object, check that bar is a valid method (even if bar is the constructor - use __construct() instead);
  • if not, and if foo is an object, check that getBar is a valid method;
  • if not, and if foo is an object, check that isBar is a valid method;
  • if not, and if foo is an object, check that hasBar is a valid method;
  • if not, return a null value.
foo['bar'] on the other hand only works with PHP arrays:
  • check if foo is an array and bar a valid element;
  • if not, return a null value.
If you need access a dynamic attribute:
{{ attribute(foo, 'data-foo') }}

Executing Statements:

Twig uses {% %} syntax to execute statements.

Setting Variables:

{% set x = 123 %}
{% set name = 'Name: !name'|t('!name', list.name) %}

Conditionally Outputting a Region:

{% if message %}
 <div class="message">{{ message }}</div>
{% endif %}

Looping:

<ul>
{% for item in list %}
  <li>{{ item.title }}: ${{item.price}}</li>
{% endfor %}
</ul>

Commenting

Twig uses {# #} syntax or comments.
{# Comments go inside these brackets. #}
You can also do multiline comments:
{#
  This comment spans
  multiple lines.
#}
A notable use for this is the twig file DocBlock. For example:
{#
/**
 * @file
 * Default theme implementation for a region.
 *
 * Available variables:
 * - content: The content for this region, typically blocks.
 * - attributes: Remaining HTML attributes for the element, including:
 *   - class: HTML classes that can be used to style contextually through CSS.
 *
 * @see template_preprocess_region()
 *
 * @ingroup themeable
 */
#}

Filters

Filters can be used to modify variables and expressions.
{{ "Some String"|t }}
Here are some common Drupal-specific filters:
  • trans/t: Runs variable through Drupal t() function. (Note: Do not pass variables through the translation filter as this is a potential security vulnerability.)
  • placeholder: Escapes content to HTML and passes through drupal_placeholder(), which emphasizes text (i.e. <em>foo</em>).
  • clean_class: Prepares a string for use as a class name.
  • clean_id: Prepares a string for use as an id.
  • format_date: Prepares a timestamp for use as a formatted date.
  • raw: Marks value as being safe which means no escaping will take place. This should be avoided if possible.
  • render: Wrapper for the render() function.
  • safe_join: Joins several strings together with a specified separator (e.g. {{ foo|safe_join(':') }})
  • without: Duplicates an array, excluding specified keys (e.g. {{ foo|without('bar', 'baz') }})

Twig {% trans %} tag

The Twig {% trans %} block will translate the text using tokens with t() or format_plural() if the {% plural ... %} switch has been declared in the tag:
<p class="submitted">
{% trans %}
  Submitted by {{ author.name }} on {{ node.date }}
{% endtrans %}
</p>
With the {% plural ... %} switch:
{% set count = comments|length %}
{% trans %}
  {{ count }} comment was deleted successfully.
{% plural count %}
  {{ count }} comments were deleted successfully.
{% endtrans %}
If filtering the tokens inside the {% trans %} block does not work, create a token outside of the block to minimize operations inside.
{% set date = node.created|format_date('medium') %}
{% trans %}
  Node was created on {{ date }}.
{% endtrans %}

Macros

Macros are comparable with functions in regular programming languages. They are useful to put often used HTML idioms into reusable elements to not repeat yourself.
Here is a small example of a macro that renders a form element:
{% macro input(name, value, type, size) %}
   <input type="{{ type|default('text') }}" name="{{ name }}" value="{{ value|e }}" size="{{ size|default(20) }}" />
{% endmacro %}
Macros differ from native PHP functions in a few ways:
  • Default argument values are defined by using the default filter in the macro body;
  • Arguments of a macro are always optional.
  • If extra positional arguments are passed to a macro, they end up in the special varargs variable as a list of values. But as with PHP functions, macros don't have access to the current template variables.

Overriding Twig Templates

Drupal allows you to override all of the templates that are used to produce HTML markup so that you can fully control the markup that is being output within a custom theme. There are templates for each page element ranging from the high level HTML to small fields.

Twig Debug Mode

To enable Twig Debug Mode:
  • If sites/default/services.yml exists proceed to next step. Otherwise copy sites/default/default.services.yml to sites/default/services.yml.
  • Edit sites/default/services.yml.
  • Under twig.config section, set debug: true.
  • Clear cache either by clicking Clear all caches on /admin/config/development/performance or running drush cr on the command line.
Once enabled you can use dump() to output all available variables or output contents of a particular variables:
All variables:
{{ dump() }}

Contents of `foo`:
{{ dump(foo) }}

Theme Hook Suggestions

When Twig debug mode is enabled, Drupal will suggest a few possible ways to override the markup and preprocessor for particular content blocks. This will be shown in the page HTML as comments.
For example:
<!-- THEME DEBUG -->
<!-- THEME HOOK: 'block' -->
<!-- FILE NAME SUGGESTIONS:
   * block--substable-content.html.twig
   * block--system-main-block.html.twig
   * block--system.html.twig
   x block.html.twig
-->
If you wish you make your own recommendations, you hook into the preprocessor for this particular element and make your own additional suggestions.
<?php
/**
* Implements hook_theme_suggestions_block_alter() for block templates.
*/
function substable_theme_suggestions_block_alter(array &$suggestions, array $variables) {
  $suggestions[] = 'block__substable';
  $suggestions[] = 'block__substable__' . $variables['elements']['#id'];
}
?>
If you clear your cache and look again at the comments you should see the new suggestion in the list.
<!-- THEME DEBUG -->
<!-- THEME HOOK: 'block' -->
<!-- FILE NAME SUGGESTIONS:
   * block--substable--substable-content.html.twig
   * block--substable.html.twig
   * block--substable-content.html.twig
   * block--system-main-block.html.twig
   * block--system.html.twig
   x block.html.twig
-->
Now you can create templates/block--substable.html.twig or block--substable--substable-content.html.twig, to override core block behavior.
The earlier a file name is in the file name suggestions above, the higher priority it will have. So by pushing to the end of the suggestions array, we are setting our template suggestions to have the highest possible priority.
Make sure you clear your cache after creating any new template files.

Including Twig Templates

The include statement includes a template and returns the rendered content of that file into the current namespace:
{% include 'header.html' %}
    Body
{% include 'footer.html' %}
Included templates have access to the variables of the active context.
You can add additional variables by passing them after the with keyword:
{# template.html will have access to the variables from the current context and the additional ones provided #}
{% include 'template.html' with {'foo': 'bar'} %}

{% set vars = {'foo': 'bar'} %}
{% include 'template.html' with vars %}
You can disable access to the context by appending the only keyword:
{# only the foo variable will be accessible #}
{% include 'template.html' with {'foo': 'bar'} only %}
{# no variables will be accessible #}
{% include 'template.html' only %}

Extending Twig Templates

The extends tag can be used to extend a template from another one. Let's define a base template, base.html, which defines a simple HTML skeleton document:
<!DOCTYPE html>
<html>
    <head>
        {% block head %}
            <link rel="stylesheet" href="style.css" />
            <title>{% block title %}{% endblock %} - My Webpage</title>
        {% endblock %}
    </head>
    <body>
        <div id="content">{% block content %}{% endblock %}</div>
        <div id="footer">
            {% block footer %}
                &copy; Copyright 2011 by <a href="http://domain.invalid/">you</a>.
            {% endblock %}
        </div>
    </body>
</html>
In this example, the block tags define four blocks that child templates can fill in.
All the block tag does is to tell the template engine that a child template may override those portions of the template.
A child template might look like this:
{% extends "base.html" %}

{% block title %}Index{% endblock %}
{% block head %}
    {{ parent() }}
    <style type="text/css">
        .important { color: #336699; }
    </style>
{% endblock %}
{% block content %}
    <h1>Index</h1>
    <p class="important">
        Welcome on my awesome homepage.
    </p>
{% endblock %}
The extends tag is the key here. It tells the template engine that this template "extends" another template. When the template system evaluates this template, first it locates the parent. The extends tag should be the first tag in the template.
Note that since the child template doesn't define the footer block, the value from the parent template is used instead.

Preprocessors

The Drupal 8 preprocessor layer sits directly between the data and the template layers. It should be used for preparing variables to be used by the template, but not perform any of the actual rendering, as that should be handled by Twig instead.

Preprocessing for template files

If the theme implementation is a template file, several functions are called before the template file is invoked to modify the variables that are passed to the template. These make up the "preprocessing" phase, and are executed (if they exist), in the following order (note that in the following list, HOOK indicates the hook being called or a less specific hook. For example, if '#theme' => 'node__article' is called, hook is node__article and nodeMODULE indicates a module name, THEME indicates a theme name, and ENGINE indicates a theme engine name). Modules, themes, and theme engines can provide these functions to modify how the data is preprocessed, before it is passed to the theme template:
  • template_preprocess(&$variables, $hook): Creates a default set of variables for all theme hooks with template implementations. Provided by Drupal Core.
  • template_preprocess_HOOK(&$variables): Should be implemented by the module that registers the theme hook, to set up default variables.
  • MODULE_preprocess(&$variables, $hook)hook_preprocess() is invoked on all implementing modules.
  • MODULE_preprocess_HOOK(&$variables)hook_preprocess_HOOK() is invoked on all implementing modules, so that modules that didn't define the theme hook can alter the variables.
  • ENGINE_engine_preprocess(&$variables, $hook): Allows the theme engine to set necessary variables for all theme hooks with template implementations.
  • ENGINE_engine_preprocess_HOOK(&$variables): Allows the theme engine to set necessary variables for the particular theme hook.
  • THEME_preprocess(&$variables, $hook): Allows the theme to set necessary variables for all theme hooks with template implementations.
  • THEME_preprocess_HOOK(&$variables): Allows the theme to set necessary variables specific to the particular theme hook.

CSS Creation

In a notable change from Drupal 7, CSS class creation has been moved out of preprocessors and directly into templates themselves. To better illustrate, see the following example from CSS classes being moved from preprocess to Twig templates:

The Old Approach

<?php
function template_preprocess_field(&$variables, $hook) {
  // ...
  $variables['attributes']['class'] = array(
    'field',
    'field-' . $variables['entity_type_css'] . '--' . $variables['field_name_css'],
    'field-name-' . $variables['field_name_css'],
    'field-type-' . $variables['field_type_css'],
    'field-label-' . $element['#label_display'],
  );
  // ...
}
?>
<div{{ attributes }}>
  {% if not label_hidden %}
    <div class="field-label{% if title_attributes.class %} {{ title_attributes.class }}{% endif %}"{{ title_attributes|without('class') }}>{{ label }}:&nbsp;</div>
  {% endif %}
  <div class="field-items"{{ content_attributes }}>
    {% for delta, item in items %}
      <div class="field-item"{{ item_attributes[delta] }}>{{ item }}</div>
    {% endfor %}
  </div>
</div>

The New Approach

<?php
function template_preprocess_field(&$variables, $hook) {
  // ...
  $variables['entity_type'] = $element['#entity_type'];
  $variables['field_name'] = $element['#field_name'];
  $variables['field_type'] = $element['#field_type'];
  $variables['label_display'] = $element['#label_display'];
  // ...
}
?>
{%
  set classes = [
    'field',
    'field-' ~ entity_type|clean_class ~ '--' ~ field_name|clean_class,
    'field-name-' ~ field_name|clean_class,
    'field-type-' ~ field_type|clean_class,
    'field-label-' ~ label_display|clean_class,
    label_display == 'inline' ? 'clearfix',
  ]
%}
{%
  set title_classes = [
    'field-label',
    label_display == 'visually_hidden' ? 'visually-hidden'
  ]
%}
<div{{ attributes.addClass(classes) }}>
  {% if not label_hidden %}
    <div{{ title_attributes.addClass(title_classes) }}>{{ label }}:&nbsp;</div>
  {% endif %}
  <div{{ content_attributes.addClass('field-items') }}>
    {% for delta, item in items %}
      <div{{ item_attributes[delta].addClass('field-item') }}>{{ item }}</div>
    {% endfor %}
  </div>
</div>

Back end development (coding)


https://github.com/WidgetsBurritos/d8-studyguide/blob/master/4-back-end-development/README.md

Ref: https://github.com/WidgetsBurritos/d8-studyguide