Академический Документы
Профессиональный Документы
Культура Документы
Lakshmi Narasimhan
This book is for sale at http://leanpub.com/drupal8book
This version was published on 2015-01-29
This is a Leanpub book. Leanpub empowers authors and publishers with the Lean Publishing
process. Lean Publishing is the act of publishing an in-progress ebook using lightweight tools and
many iterations to get reader feedback, pivot until you have the right book and build traction once
you do.
This work is licensed under a Creative Commons Attribution 3.0 Unported License
Contents
Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Cover image attribution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
i
i
Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
ii
Basic concepts . . . . . . . . .
Drupal 8 directory structure
Classes and OOP . . . . . .
Namespaces . . . . . . . . .
Using Drupalconsole . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1
1
1
1
1
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
3
3
3
3
3
Configuration management . . . . . . . .
Variables RIP . . . . . . . . . . . . . . .
What parts of your site are configurable?
Example configuration . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
5
5
5
5
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
6
6
6
6
6
Designing forms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
The forms class hierarchy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Creating custom forms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7
7
7
Writing plugins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
When should you write a plugin? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
What constitutes a plugin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8
8
8
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
CONTENTS
8
8
8
Entities . . . . . . . . . . . . . . . . . . . .
Creating custom entites . . . . . . . . . .
Entity CRUD hooks . . . . . . . . . . . .
Storing entity information in annotation
Entities used in core . . . . . . . . . . . .
Example entity . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
9
9
9
9
9
9
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
10
10
10
10
10
Building views . . . . . . . . . . . . . . . . . . . . . . . .
Data integration: exposing your module to views . . . .
Data handlers: field, filter and argument views handlers
Other views plugins . . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
11
11
11
11
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
12
12
12
12
Testing . . . . .
PHPUnit . . .
Simpletest . .
Example code
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
13
13
13
13
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
14
14
14
14
14
15
15
15
16
16
16
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
CONTENTS
routing.yml . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
libraries.yml . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
settings.yml . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
16
16
18
Acknowledgments
Cover image attribution
Electric Sphere by spettacolopuro is licensed under CC BY 2.0
Drupal is a registered trademark of Dries Buytaert.
https://www.flickr.com/photos/spettacolopuro/3842161463
https://www.flickr.com/photos/spettacolopuro/
http://creativecommons.org/licenses/by/2.0/
Introduction
Basic concepts
Drupal 8 directory structure
Classes and OOP
Namespaces
Using Drupalconsole
Though Drupal 8 is technically advanced compared to its predecessor, writing a module involves a
lot of boilerplate code. There w many gotcha moments when you will forget to add a namespace
and get puzzling errors.
Fortunately, all that code can be generated automatically using a tool called the Drupal Console.
Drupal Console is another cool addition to the Proudly Found Elsewhere school of thought as it
leverages the Symfony Console component to handle the CLI part.
Installing
Note that Drupal Console supports only Drupal 8.0.0-beta4 at the time of writing this.
Get the latest version:
1
$ mv console.phar /usr/local/bin/drupal
Go to the drupal root directory of any Drupal 8 beta4 setup and run drupal list to get something
like:
http://drupalconsole.com/
https://prague2013.drupal.org/session/not-invented-here-proudly-found-elsewhere-drupal-8-story
http://symfony.com/doc/current/components/console/index.html
Basic concepts
1
2
3
4
5
6
7
8
9
Usage
Drupal Console currently supports generating PSR-4 compliant code for plugins, controllers,
modules, services, entities and forms.It also has basic debugging commands for listing current
configuration and routes.
It is always a good practice to write a service which does only one thing and does it really
well, akin to the UNIX tools philosophy.
Example service
Tagged services
Services used in core
Many services in core are replacements of global variables which existed in Drupal 7. The most
notorious example of global variable usage was the $user case.
In Drupal 7, one could write
1
2
3
4
global $user;
if ($user->uid == 0) {
//user is not logged in
}
if (\Drupal::currentUser()->isAuthenticated() == 0) {
//user is not logged in
}
Configuration management
Variables RIP
What parts of your site are configurable?
Example configuration
Designing forms
The forms class hierarchy
Creating custom forms
Writing plugins
When should you write a plugin?
What constitutes a plugin
The plugin annotation system
Plugins used in core
Example plugin
Entities
Creating custom entites
Entity CRUD hooks
Storing entity information in annotation
Entities used in core
Example entity
Building views
Data integration: exposing your module to views
Data handlers: field, filter and argument views
handlers
Other views plugins
Testing
PHPUnit
Simpletest
Example code
colorbox:
version: VERSION
js:
js/colorbox.js: {}
dependencies:
- core/jquery
- core/drupal
Here, colorbox is the name of the asset bundle to be included. This identifier will be used to refer
the asset in the module or another yml file. The js property lists all the js files needed for the asset.
The {} next to it can be used for specifying metadata like cache, preprocess, minify and weight.
The dependencies are the assets list which colorbox expects to be loaded. The core/jquery means
the jquery asset present in core.libraries.yml.
Heres how the jquery entry looks in core.libraries.yml:
1
2
3
4
5
6
7
8
9
17
jquery:
remote: https://github.com/jquery/jquery
version: 2.1.0
license:
name: MIT
url: https://github.com/jquery/jquery/blob/2.1.0/MIT-LICENSE.txt
gpl-compatible: true
js:
assets/vendor/jquery/jquery.js: { weight: -20 }
classList:
remote: https://github.com/eligrey/classList.js
# @todo Stable release required for Drupal 8.0.
version: master
license:
name: Public Domain
url: https://github.com/eligrey/classList.js/blob/master/LICENSE.md
gpl-compatible: true
js:
assets/vendor/classList/classList.min.js: { weight: -21, browsers: { IE: 'lt\
e IE 9', '!IE': false }, minified: true }
Note that it is possible to add comments in YML files(They start with a #).
Likewise, the core/drupal dependency needs to be put up if the respective js exposes a Drupal
setting.
Colorbox itself listed as a dependency in colorbox.libraries.yml for a theme variant:
1
2
3
4
5
6
7
8
9
10
11
stockholmsyndrome:
version: VERSION
js:
styles/stockholmsyndrome/colorbox_style.js: {}
css:
theme:
styles/stockholmsyndrome/colorbox_style.css: {}
dependencies:
- colorbox/colorbox
- core/jquery
- core/drupal
18
function colorbox_page_attachments(&$page) {
...
$page['#attached']['library'][] = 'colorbox/colorbox';
Configurables can be passed from Drupal/PHP domain to js using the drupalSettings key.
1
2
3
4
5
6
7
8
9
$js_settings = array(
'opacity' => '0.85',
'current' => t('{current} of {total}'),
'previous' => t(' Prev'),
'next' => t('Next '),
'close' => t('Close'),
'maxWidth' => '98%',
);
$page['#attached']['drupalSettings']['colorbox'] = $js_settings;
Much of libraries.yml functionality overlaps with the hook_libraries_info of libraries module. The
same thing can be accomplished by implementing the libraries_info hook, downloading colorbox
jquery release in the libraries directory and calling:
1
libraries_load('colorbox', $variant);
settings.yml
https://www.drupal.org/node/1775738