Drupal 8 for Developers: Difference between revisions

From Training Material
Jump to navigation Jump to search
mNo edit summary
 
(4 intermediate revisions by the same user not shown)
Line 14: Line 14:
{{Can I use your material}}
{{Can I use your material}}


== Overview of Drupal ==
== Overview of Drupal ==


* What Is Drupal?
* What Is Drupal?
Line 20: Line 20:
* Drupal '''Add-Ons''': ''Modules'', ''Themes'', ''Distributions'', and ''Translations''
* Drupal '''Add-Ons''': ''Modules'', ''Themes'', ''Distributions'', and ''Translations''


== Overview Con't ==
== Overview Con't ==
Major '''subsystems''' in Drupal
Major '''subsystems''' in Drupal
* Routing, Menus
* Routing, Menus
Line 29: Line 29:
* <small>''[https://www.drupal.org/docs/drupal-apis Related docs]''</small>
* <small>''[https://www.drupal.org/docs/drupal-apis Related docs]''</small>


=== Routing ===
=== Routing ===
* Handles '''interactions'''  
* Handles '''interactions'''  
** user (or system) accessing a certain path (or resource)
** user (or system) accessing a certain path (or resource)
Line 39: Line 39:
* <small>''[https://www.drupal.org/docs/drupal-apis/routing-system Related docs]''</small>
* <small>''[https://www.drupal.org/docs/drupal-apis/routing-system Related docs]''</small>


=== Entities ===
=== Menus ===
* Navigation
** provides details about how the site itself is '''organized'''
** keeps a '''structure''' of how content is '''related'''
* Provide APIs to generate, retrieve, and modify elements of the site structure
* '''Hierarchical''' - have a tree-like structure
* <small>''Related [https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Menu%21menu.api.php/group/menu/9.4.x Menu API]''</small>
* <small>''[https://www.drupal.org/docs/drupal-apis/menu-api Related docs]''</small>
 
 
=== Entities ===
* Powerful way of '''modeling data and content''' in Drupal
* Powerful way of '''modeling data and content''' in Drupal
* ''Node'', ''taxonomy'', ''user'', ''comment'', ''file'', ''media'', etc - or our '''custom''' one
* ''Node'', ''taxonomy'', ''user'', ''comment'', ''file'', ''media'', etc - or our '''custom''' one
Line 50: Line 60:
* <small>''[https://www.drupal.org/docs/drupal-apis/entity-api Related docs]''</small>
* <small>''[https://www.drupal.org/docs/drupal-apis/entity-api Related docs]''</small>


=== Fields ===
=== Fields ===
* '''Entity bundles''' can have various fields
* '''Entity bundles''' can have various fields
* Are responsible for '''holding data'''
* Are responsible for '''holding data'''
Line 59: Line 69:
*** '''exported''' via configuration
*** '''exported''' via configuration


==== Fields con't ====
==== Fields con't ====
* Can also be of '''multiples types''', depending on the data they store
* Can also be of '''multiples types''', depending on the data they store
** string (or text) fields, numeric, date, email, and so on
** string (or text) fields, numeric, date, email, and so on
Line 68: Line 78:
* <small>''[https://www.drupal.org/docs/drupal-apis/entity-api/fieldtypes-fieldwidgets-and-fieldformatters Related docs]''</small>
* <small>''[https://www.drupal.org/docs/drupal-apis/entity-api/fieldtypes-fieldwidgets-and-fieldformatters Related docs]''</small>


=== Menus ⌘===
* Navigation
** provides details about how the site itself is '''organized'''
** keeps a '''structure''' of how content is '''related'''
* Provide APIs to generate, retrieve, and modify elements of the site structure
* '''Hierarchical''' - have a tree-like structure
* <small>''Related [https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Menu%21menu.api.php/group/menu/9.4.x Menu API]''</small>
* <small>''[https://www.drupal.org/docs/drupal-apis/menu-api Related docs]''</small>


=== Views ===
=== Views ===
* '''Listing''' content and data
* '''Listing''' content and data
* Allows the creation of '''configurable''' listings
* Allows the creation of '''configurable''' listings
Line 84: Line 86:
* <small>''Related [https://api.drupal.org/api/drupal/core%21modules%21views%21views.api.php/group/views_overview/9.4.x Views API]''</small>
* <small>''Related [https://api.drupal.org/api/drupal/core%21modules%21views%21views.api.php/group/views_overview/9.4.x Views API]''</small>


=== Forms ===
=== Forms ===
* Capture user input  
* Capture user input  
* Powerful Form API
* Powerful Form API
Line 93: Line 95:
* <small>''[https://www.drupal.org/docs/drupal-apis/form-api Related docs]''</small>
* <small>''[https://www.drupal.org/docs/drupal-apis/form-api Related docs]''</small>


=== Configuration ===
=== Configuration ===
* '''Centralized''' configuration system
* '''Centralized''' configuration system
* Can be stored in: '''database''' (default), '''files''' in a specific dir, '''other''' storage back-ends
* Can be stored in: '''database''' (default), '''files''' in a specific dir, '''other''' storage back-ends
Line 103: Line 105:
* <small>''[https://www.drupal.org/docs/drupal-apis/configuration-api Related docs]''</small>
* <small>''[https://www.drupal.org/docs/drupal-apis/configuration-api Related docs]''</small>


=== Plugins ===
=== Plugins ===
* '''Encapsulating''' functionality - very widely used in D9
* '''Encapsulating''' functionality - very widely used in D9
* Components of '''reusable''' code - used and managed by a central system
* Components of '''reusable''' code - used and managed by a central system
Line 124: Line 126:
* <small>''[https://www.drupal.org/docs/drupal-apis/plugin-api Related docs]''</small>
* <small>''[https://www.drupal.org/docs/drupal-apis/plugin-api Related docs]''</small>


=== The theme system ===
=== The theme system ===
* Is spread out over Drupal core, modules, and themes
* Is spread out over Drupal core, modules, and themes
* Both '''modules and themes''' can theme data or content
* Both '''modules and themes''' can theme data or content
Line 135: Line 137:
* <small>''[https://www.drupal.org/docs/theming-drupal Related docs]''</small>
* <small>''[https://www.drupal.org/docs/theming-drupal Related docs]''</small>


=== Caching ===
=== Caching ===
* Improves the '''performance''' of building pages and rendering data
* Improves the '''performance''' of building pages and rendering data
* '''Cache backend''' - stores the results of complex data calculations
* '''Cache backend''' - stores the results of complex data calculations
Line 143: Line 145:
* <small>''[https://www.drupal.org/docs/drupal-apis/cache-api Related docs]''</small>
* <small>''[https://www.drupal.org/docs/drupal-apis/cache-api Related docs]''</small>


== The Evolution of Drupal ==
== The Evolution of Drupal ==
Changes introduced in Drupal 8:
Changes introduced in Drupal 8:
* improved '''the usability and accessibility''' of the administrative UI
* improved '''the usability and accessibility''' of the administrative UI
Line 155: Line 157:
*** usable by other open-source projects
*** usable by other open-source projects


=== Changes in internal systems and APIs ===
=== Changes in internal systems and APIs ===
* URL request handler from the '''Symfony'''
* URL request handler from the '''Symfony'''
* Swappable '''services''' (also from Symfony)
* Swappable '''services''' (also from Symfony)
Line 170: Line 172:
* '''Views''' in core, Poll out of the core, etc
* '''Views''' in core, Poll out of the core, etc


== Handling HTTP Requests ==
== Handling HTTP Requests ==
* The main Drupal ''index.php'' file is loaded and executed by the server to handle the request
* The main Drupal ''index.php'' file is loaded and executed by the server to handle the request
* Drupal 8 uses Symfony to handle HTTP requests
* Drupal 8 uses Symfony to handle HTTP requests
Line 182: Line 184:
** Symfony handles the req and returns result to browser
** Symfony handles the req and returns result to browser


=== Symfony HTTP request system in Drupal 8 ===
=== Symfony HTTP request system in Drupal 8 ===


* Modules can register '''routes''', which map URLs and conditions (context) to '''controller''' classes
* Modules can register '''routes''', which map URLs and conditions (context) to '''controller''' classes
Line 197: Line 199:
*** providing dynamic URL routes
*** providing dynamic URL routes


== Cache in Drupal ==
== Cache in Drupal ==


* System, which allows modules to precalculate data or output and store it
* System, which allows modules to precalculate data or output and store it
Line 205: Line 207:
*** when data is invalidated (changes in dependent data), any module that uses caching needs to clear it
*** when data is invalidated (changes in dependent data), any module that uses caching needs to clear it


=== Examples of cached information ===
=== Examples of cached information ===


* Page output for anonymous users (can be disabled on Performance config page)
* Page output for anonymous users (can be disabled on Performance config page)
Line 214: Line 216:
* Theme information (list of theme regions, theme-related info from modules and themes)
* Theme information (list of theme regions, theme-related info from modules and themes)


=== Cache API in Drupal 8 ===
=== Cache API in Drupal 8 ===


* Services do the job
* Services do the job
Line 228: Line 230:
*** set(), get(), invalidate(), etc
*** set(), get(), invalidate(), etc


==== Clearing caches ====
==== Clearing caches ====


* When we use default core cache bins, it will be flushed automatically
* When we use default core cache bins, it will be flushed automatically
Line 250: Line 252:
</small>
</small>


==== Tagging mechanism ====
==== Tagging mechanism ====


* To flush parts of the cache when data they’re related to is changed or removed
* To flush parts of the cache when data they’re related to is changed or removed
Line 264: Line 266:
** Custom tags<br><syntaxhighlight lang="php">\Drupal\Core\Cache\Cache::invalidateTags($tags);</syntaxhighlight>
** Custom tags<br><syntaxhighlight lang="php">\Drupal\Core\Cache\Cache::invalidateTags($tags);</syntaxhighlight>


== Automatic Class Loading in Drupal ==
== Automatic Class Loading in Drupal ==


* Automatic loading of files containing PHP '''class''', '''interface''', and '''trait''' declarations
* Automatic loading of files containing PHP '''class''', '''interface''', and '''trait''' declarations
Line 271: Line 273:
** Reduce the burden on developers by automatically loading files containing class definitions (instead of making them load the classes explicitly in code)
** Reduce the burden on developers by automatically loading files containing class definitions (instead of making them load the classes explicitly in code)


=== Drupal 8 Specific Way ===
=== Drupal 8 Specific Way ===


* Incorporates the '''class loader''' from the ''Composer''
* Incorporates the '''class loader''' from the ''Composer''
Line 286: Line 288:
** The directory that each class file goes in depends on its namespace (examples in the next slide)
** The directory that each class file goes in depends on its namespace (examples in the next slide)


==== Dirs and namespaces, Examples ====
==== Dirs and namespaces, Examples ====
Relations between dirs and namespaces
Relations between dirs and namespaces
* Add-on module’s class  
* Add-on module’s class  
Line 301: Line 303:
  'vendor/symfony/dependency-injection/Container.php'
  'vendor/symfony/dependency-injection/Container.php'


==== Drupal 8 OOP Examples (Not Yet In D9, works only in D8) ====
==== Drupal 8 OOP Examples (Not Yet In D9, works only in D8) ====
<small>
<small>
Modules to enable: ''oop_examples'', ''oop_design_patterns''
Modules to enable: ''oop_examples'', ''oop_design_patterns''
Line 310: Line 312:
<!-- TODOS starts here -->
<!-- TODOS starts here -->


== Drupal Rules, Programming ==
== Drupal Rules, Programming ==


* Alterability
* Alterability
Line 320: Line 322:
* Tests, Documentation
* Tests, Documentation


=== Alterability ===
=== Alterability ===


* Drupal core and contributed modules are almost fully alterable
* Drupal core and contributed modules are almost fully alterable
Line 332: Line 334:
** YAML-based menu
** YAML-based menu


==== Drupal Hooks ====
==== Drupal Hooks ====
* PHP file or function you can put into a module or theme
* PHP file or function you can put into a module or theme
* Will be '''invoked''' (called or included) at an appropriate time by a Drupal core or contributed module  
* Will be '''invoked''' (called or included) at an appropriate time by a Drupal core or contributed module  
Line 351: Line 353:
</small>
</small>


==== Drupal Plugins ====
==== Drupal Plugins ====


* Replaced many of the generic hooks from Drupal 7 with an object-oriented system  
* Replaced many of the generic hooks from Drupal 7 with an object-oriented system  
Line 368: Line 370:
</small>
</small>


==== Drupal Dependency Injection ====
==== Drupal Dependency Injection ====


* Allows modules to replace fundamental core systems of Drupal (or services)
* Allows modules to replace fundamental core systems of Drupal (or services)
** for example the mechanism for storing cached data
** for example the mechanism for storing cached data


==== Drupal Routing ====
==== Drupal Routing ====


* Symfony-based routing system
* Symfony-based routing system
Line 379: Line 381:
** allows to alter what happens at various points during an HTTP request by defining event subscribers
** allows to alter what happens at various points during an HTTP request by defining event subscribers


==== Drupal Links ====
==== Drupal Links ====


* YAML-based system  
* YAML-based system  
Line 394: Line 396:
-->
-->


==== Drupal Module Themeable, Output ====
==== Drupal Module Themeable, Output ====


* Render arrays should be returned from all functions that return output
* Render arrays should be returned from all functions that return output
Line 410: Line 412:
<!-- TODO: Do all those empty sections below -->
<!-- TODO: Do all those empty sections below -->


=== Separation of: Content, Configuration, State Data  ===
=== Separation of: Content, Configuration, State Data  ===
* '''Content''' - Entities, Bundles, Fields, data in db
* '''Content''' - Entities, Bundles, Fields, data in db
* '''Configuration''' - setups, YAML files, definitions
* '''Configuration''' - setups, YAML files, definitions
Line 419: Line 421:
** <small>[https://www.drupal.org/docs/drupal-apis/state-api Related docs]</small>
** <small>[https://www.drupal.org/docs/drupal-apis/state-api Related docs]</small>


=== i18n (internationalization) ===
=== i18n (internationalization) ===
* Drupal translations - <small>''https://localize.drupal.org/''</small>
* Drupal translations - <small>''https://localize.drupal.org/''</small>
* Related <small>''[https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Language%21language.api.php/group/i18n/9.4.x i18n API]''</small>
* Related <small>''[https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Language%21language.api.php/group/i18n/9.4.x i18n API]''</small>
* <small>''[https://www.drupal.org/docs/8/api/translation-api/overview Related docs]''</small>
* <small>''[https://www.drupal.org/docs/8/api/translation-api/overview Related docs]''</small>


=== Accessibility, Usability ===
=== Accessibility, Usability ===
* Accessibility
* Accessibility
** <small>''[https://www.drupal.org/docs/accessibility Related docs]''</small>
** <small>''[https://www.drupal.org/docs/accessibility Related docs]''</small>
Line 430: Line 432:
**  <small>''[https://www.drupal.org/docs/develop/user-interface-standards Related docs]''</small>
**  <small>''[https://www.drupal.org/docs/develop/user-interface-standards Related docs]''</small>


=== DB Independence (database) ===
=== DB Independence (database) ===
* <small>''Related [https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Database%21database.api.php/group/database/9.4.x DB API]''</small>
* <small>''Related [https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Database%21database.api.php/group/database/9.4.x DB API]''</small>
* <small>''[https://www.drupal.org/docs/drupal-apis/database-api Related docs]''</small>
* <small>''[https://www.drupal.org/docs/drupal-apis/database-api Related docs]''</small>


=== Security (all user-provided input is insecure) ===
=== Security (all user-provided input is insecure) ===
* <small>''Related [https://api.drupal.org/api/drupal/core%21core.api.php/group/best_practices/9.4.x Security API]''</small>
* <small>''Related [https://api.drupal.org/api/drupal/core%21core.api.php/group/best_practices/9.4.x Security API]''</small>
* <small>''[https://www.drupal.org/docs/security-in-drupal Related docs]''</small>
* <small>''[https://www.drupal.org/docs/security-in-drupal Related docs]''</small>


=== Tests, Documentation ===
=== Tests, Documentation ===


* Should we bother at all, huh?
* Should we bother at all, huh?
Line 444: Line 446:
** Yes, everything should be documented
** Yes, everything should be documented


==== Everything should be tested ====
==== Everything should be tested ====


* SimpleTest, PHPUnit - both adopted in D8, 1st deprecated (new tests should be written with 2nd)  
* SimpleTest, PHPUnit - both adopted in D8, 1st deprecated (new tests should be written with 2nd)  
Line 451: Line 453:
* Adopted also by lots of contributed modules (to some extent, at least)
* Adopted also by lots of contributed modules (to some extent, at least)


==== Everything should be documented ====
==== Everything should be documented ====


* standards for in-code documentation
* standards for in-code documentation
Line 462: Line 464:
*** and 'Do Not Ask Over and Over The Same Boring Questions' (that's the lighter version, for sure!)
*** and 'Do Not Ask Over and Over The Same Boring Questions' (that's the lighter version, for sure!)


== Drupal Mistakes, Programming ==
== Drupal Mistakes, Programming ==


* Programming Too Much
* Programming Too Much
Line 469: Line 471:
* Working Alone
* Working Alone


=== Programming Too Much ===
=== Programming Too Much ===
* Avoiding Custom Programming with Fielded Data
* Avoiding Custom Programming with Fielded Data
* Defining Theme Regions for Block Placement
* Defining Theme Regions for Block Placement


=== Over-Executing Code ===
=== Over-Executing Code ===


* Executing Code on Every Page Load
* Executing Code on Every Page Load
* Using an Overly General Hook
* Using an Overly General Hook


=== Saving PHP Code in the Database ===
=== Saving PHP Code in the Database ===


* It's hacking
* It's hacking
Line 486: Line 488:
** Hard to track
** Hard to track


==== Alternatives for php code in db ====
==== Alternatives for php code in db ====
* Control '''block''' visibility
* Control '''block''' visibility
** Use '''Context''' or '''Layout Builder''' modules, which allow much more '''flexibility on block placement'''
** Use '''Context''' or '''Layout Builder''' modules, which allow much more '''flexibility on block placement'''
Line 498: Line 500:
** Create your own custom field or formatter
** Create your own custom field or formatter


=== Working Alone ===
=== Working Alone ===


* Participating in Groups and IRC
* Participating in Groups and IRC
Line 504: Line 506:
* Contributing to the Drupal Community in Other Ways
* Contributing to the Drupal Community in Other Ways


== Programming Examples ==
== Programming Examples ==


* Module skeleton
* Module skeleton
Line 512: Line 514:
* Programming with Entities and Fields
* Programming with Entities and Fields


=== Module skeleton ===
=== Module skeleton ===
<small>'''Exercises:'''
<small>'''Exercises:'''
* [[Drupal_8_for_Developers#1._Create_your_own_module|Create your own module]]
* [[Drupal_8_for_Developers#1._Create_your_own_module|Create your own module]]
</small>
</small>


=== Registering for URLs and Displaying Content ===
=== Registering for URLs and Displaying Content ===


* Registering for a URL in Drupal 8
* Registering for a URL in Drupal 8
Line 530: Line 532:
* Generating paged output
* Generating paged output


==== Page callback, menu link ====
==== Page callback, menu link ====
<small>
<small>
Related D8 api/doc references:
Related D8 api/doc references:
Line 545: Line 547:
</small>
</small>


==== Block, plugin, annotation ====
==== Block, plugin, annotation ====
<small>
<small>
Related D8 api/doc references:
Related D8 api/doc references:
Line 558: Line 560:
</small>
</small>


=== Using the Drupal Form API ===
=== Using the Drupal Form API ===


* Form Arrays, Form State Arrays, and Form State Objects
* Form Arrays, Form State Arrays, and Form State Objects
Line 566: Line 568:
* Altering Forms
* Altering Forms


=== Programming with Ajax in Drupal ===
=== Programming with Ajax in Drupal ===


* Setting Up a Form for Ajax
* Setting Up a Form for Ajax
Line 572: Line 574:
* Command-based Ajax Callback Functions in Drupal 8
* Command-based Ajax Callback Functions in Drupal 8


==== Form, validation, submit, ajax ====
==== Form, validation, submit, ajax ====
<small>
<small>
<!-- TODO
<!-- TODO
Line 585: Line 587:
</small>
</small>


=== Programming with Entities and Fields ===
=== Programming with Entities and Fields ===


* Terminology of Entities and Fields
* Terminology of Entities and Fields
Line 595: Line 597:
* Programming with Field Formatters
* Programming with Field Formatters


==== Entity, field ====
==== Entity, field ====
<small>
<small>
<!-- TODO
<!-- TODO
Line 608: Line 610:
</small>
</small>


== Programming Tools and Tips ==
== Programming Tools and Tips ==
* Where to Find More Information
* Where to Find More Information
** Drupal Site Building and General Drupal Information
** Drupal Site Building and General Drupal Information
Line 620: Line 622:
** https://github.com/mglaman/drupal-check
** https://github.com/mglaman/drupal-check


=== Command liners ===
=== Command liners ===
* '''Composer''' - packages manager, updater
* '''Composer''' - packages manager, updater
** <small>''https://getcomposer.org/doc/''</small>
** <small>''https://getcomposer.org/doc/''</small>
Line 628: Line 630:
** <small>''https://drupalconsole.com/docs/en//''</small>
** <small>''https://drupalconsole.com/docs/en//''</small>


=== Other Useful Modules ===
=== Other Useful Modules ===
* https://www.drupal.org/project/pingme
* https://www.drupal.org/project/pingme
* https://www.drupal.org/project/drush9_example
* https://www.drupal.org/project/drush9_example


=== Errors logging ===
=== Errors logging ===
Enable logging all errors (only on testing envi!):
Enable logging all errors (only on testing envi!):
  /admin/config/development/logging
  /admin/config/development/logging
Line 647: Line 649:
</syntaxhighlight>
</syntaxhighlight>


== Exercises ==
== Exercises ==


=== 1. Create your own module ===
=== 1. Create your own module ===
Line 895: Line 897:
#** Hint: router file can be better (-;
#** Hint: router file can be better (-;
#** Don't forget to change the service too (---;
#** Don't forget to change the service too (---;
#** Reference: use 'token' module
# Play with dynamic parameter '''../mm'''
# Play with dynamic parameter '''../mm'''
<br>
<br>
Line 978: Line 981:
# Rewrite it into '''mm.links.task.yml'''. How?
# Rewrite it into '''mm.links.task.yml'''. How?
#* Hint: Use '''pathauto''' module as a reference
#* Hint: Use '''pathauto''' module as a reference
<!--
mm.myform:
  route_name: mm.form
  base_route: system.performance_settings
  title: 'My Form'
  weight: 10
mm.customp:
  route_name: mm.hiuniv
  base_route: system.performance_settings
  title: 'Hi univ'
  weight: 20
  path: '/admin/config/development/hiuniv'
  path: '/admin/config/development/mm-form'
-->


==== 6.2. Validate the form ====
==== 6.2. Validate the form ====

Latest revision as of 12:08, 22 May 2024

THIS IS A DRAFT

This text may not be complete.


title
Drupal 8 for Developers
author
Lukasz Sokolowski

Drupal 8 for Developers

Drupal 8 for Developers Training Materials

Overview of Drupal

  • What Is Drupal?
  • Drupal Core
  • Drupal Add-Ons: Modules, Themes, Distributions, and Translations

Overview Con't

Major subsystems in Drupal

  • Routing, Menus
  • Entities, Fields, Views, Forms
  • Configuration, Plugins
  • Theme system, Caching
  • All Drupal APIs
  • Related docs

Routing

  • Handles interactions
    • user (or system) accessing a certain path (or resource)
    • translates into a route, which maps that resource to a flow
    • returns a response back - success or graceful failure
  • Replacement for hook_menu - Symfony Routing component
  • Route mapped to a controller which renders drupal page
  • Related Routing API
  • Related docs

Menus

  • Navigation
    • provides details about how the site itself is organized
    • keeps a structure of how content is related
  • Provide APIs to generate, retrieve, and modify elements of the site structure
  • Hierarchical - have a tree-like structure
  • Related Menu API
  • Related docs


Entities

  • Powerful way of modeling data and content in Drupal
  • Node, taxonomy, user, comment, file, media, etc - or our custom one
  • Can have multiple bundles
    • different variations of the same entity type
    • can have different fields on them (while sharing some base fields)
  • New type of entity - configuration
    • exportable items, to be reused/shared in environments
  • Related Entity API
  • Related docs

Fields

  • Entity bundles can have various fields
  • Are responsible for holding data
  • Two main types - base and configurable
    • Base - defined in code for each entity type
    • Configurable - usually created and configured in the UI
      • attached to a bundle of that entity type
      • exported via configuration

Fields con't

  • Can also be of multiples types, depending on the data they store
    • string (or text) fields, numeric, date, email, and so on
  • We can create our own field types
    • with its own data input widget
    • and output formatter
  • Related Field API
  • Related docs


Views

  • Listing content and data
  • Allows the creation of configurable listings
  • Includes - filters, sorts, display options, and many other features
  • Extendable via custom plugins
  • Related Views API

Forms

  • Capture user input
  • Powerful Form API
    • securely and efficiently rendering and processing the submitted data
    • abstraction over having to output our own form elements and deal with posted values
    • allows to define our own form definition in OOP and handle validation and submission in a logical way
  • Related Form API
  • Related docs

Configuration

  • Centralized configuration system
  • Can be stored in: database (default), files in a specific dir, other storage back-ends
  • Exportable into YAML files (to be re-imported later)
  • Two kinds
    • simple - always singular (one instance only) - site name, email address, etc
    • complex - follows a certain schema and we can have multiple definitions - View, Entity, etc
  • Related Config API
  • Related docs

Plugins

  • Encapsulating functionality - very widely used in D9
  • Components of reusable code - used and managed by a central system
  • System handles a task in a certain way (plugin X)
    • other modules to provide different ways (plugin Y or Z).
  • Opposite to entities: not used for data storage, but for functionality
  • Discoverability - usually via
    • Annotations - form of DocBlock comments, borrowed from the Doctrine library
      • can describe classes(Drupal), methods, and even properties with certain metadata
    • YAML files - for example menu links
  • Related Plugin API
  • Related docs

The theme system

  • Is spread out over Drupal core, modules, and themes
  • Both modules and themes can theme data or content
  • Best practice - to ensure that modules are able to theme their data
    • themes can then come into play to style the output or override whats needed
  • D8 moved to the open source Twig templating system (twig.symfony.com)
    • separation of logic from a presentation layer
    • makes front-end developers' jobs much easier and secured
  • Related Theme API
  • Related docs

Caching

  • Improves the performance of building pages and rendering data
  • Cache backend - stores the results of complex data calculations
    • cache invalidation - something requires the calculations to be redone
  • Render cache - wraps output with metadata that describes when the cache of that output needs to be invalidated
  • Related Cache API
  • Related docs

The Evolution of Drupal

Changes introduced in Drupal 8:

  • improved the usability and accessibility of the administrative UI
  • the administrative UI and the core themes work well on mobile devices
  • procedural-code-based system transformed into a mostly object-oriented
    • incorporates code from many outside open-source projects
      • use and improve code from other projects where possible
      • don't invent everything itself
    • some of the core systems of Drupal were rewritten
      • as portable PHP classes without Drupal-specific dependencies
      • usable by other open-source projects

Changes in internal systems and APIs

  • URL request handler from the Symfony
  • Swappable services (also from Symfony)
    • many aspects of Drupal core have been converted to services (allowing contributed modules to replace them)
  • OO plugin system (from Symfony and Doctrine)
    • many of the hooks have been converted to use plugins
    • reduction of procedural code for more OO code
  • Some informational hooks have been converted to use YAML-formatted files
  • Storing configuration information has new API, easy to export and import
    • to share configuration between sites,
    • or store it in a revision control system (git, etc)
  • Templating system from the Twig
  • Class loader from the Composer
  • Views in core, Poll out of the core, etc

Handling HTTP Requests

  • The main Drupal index.php file is loaded and executed by the server to handle the request
  • Drupal 8 uses Symfony to handle HTTP requests
    • The dynamic class loader and error handlers are started (db connections, etc)
    • Loading and executing of settings.php file (can be multi-site setup, additional sites.php file required)
    • Drupal kernel starts up the Dependency Injection Container
      • defines services provided by classes, configuration system requests
    • Initialization of PHP session variables and cookies
    • For anonymous users page cache is checked (doesn't apply to 'logged-in' users)
    • Various files are loaded and executed (core include files and enabled modules' .module files)
    • Symfony handles the req and returns result to browser

Symfony HTTP request system in Drupal 8

  • Modules can register routes, which map URLs and conditions (context) to controller classes
    • Controller classes: produce generic page output, present forms and process form submissions, etc
  • The best match to the context is determined by Symfony and it chooses the controller method to execute
  • Controller returns a Symfony response object containing HTTP header and content information
  • Symfony returns the response information to browser
  • event subscribers can be also registered by modules
    • they can intercept and override lots of steps in response process
    • examples of use in core modules
      • translating URL aliases to system URL paths
      • enabling maintenance mode
      • handling language selection
      • providing dynamic URL routes

Cache in Drupal

  • System, which allows modules to precalculate data or output and store it
    • the next time it is needed it doesn’t have to be calculated again
    • saves a lot of time on page loads
    • expense is more complexity
      • when data is invalidated (changes in dependent data), any module that uses caching needs to clear it

Examples of cached information

  • Page output for anonymous users (can be disabled on Performance config page)
  • Block output (can't be turned off in Drupal 8)
  • Data collected from hooks
  • Lists with available plugins (plugin managers)
  • Form arrays
  • Theme information (list of theme regions, theme-related info from modules and themes)

Cache API in Drupal 8

  • Services do the job
    • Different sets of cached data (or bins) can use different storage mechanisms
    • Allways call, to get correct cache class
      \Drupal::cache($bin)
      
    • Instance of cache class implements
      \Drupal\Core\Cache\CacheBackendInterface
      
    • Use '$container' as an alternative
      // The name of the service for a particular cache bin is
      // 'cache.' . $bin.
      $cache_class = $container->get('cache.' . $bin);
      
    • Available methods
      • set(), get(), invalidate(), etc

Clearing caches

  • When we use default core cache bins, it will be flushed automatically
  • When custom cache system in use
    • if cache clear is requested via 'drupal_flush_all_caches()' function
      • flash data with custom 'hook_cache_flush()'
    • custom 'hook_rebuild()' may be also needed

Related D8 api/doc references:

Modules to enable: Examples for Developers, Cache example

Exercises:

  • Clear cache with
    • performance section in admin config
    • webprofiler (additional module from devel package)
    • drush
    • in your own module via hook (we'll do it later in another exercise)

Tagging mechanism

  • To flush parts of the cache when data they’re related to is changed or removed
    • Example: module is caching data related to a specific node content item
      • we tag it with the node ID
        // $cid is a unique cache ID key for your data, which is $data.
        // $nid is the ID of the node whose data is cached.
        $cache_class->set($cid, 
                          $data, 
                          CacheBackendInterface::CACHE_PERMANENT, 
                          array('node:' . $nid));
        
      • when calls to the core Node module modify this node content item, it will call cache methods to invalidate all cached data that was tagged with this node ID
    • Custom tags
      \Drupal\Core\Cache\Cache::invalidateTags($tags);
      

Automatic Class Loading in Drupal

  • Automatic loading of files containing PHP class, interface, and trait declarations
    • Integrate with PHP's native class-auto-loading system (functions can be registered as class loaders)
    • Reduce the load on the server by only loading files containing class definitions if those classes are being used in a specific page request
    • Reduce the burden on developers by automatically loading files containing class definitions (instead of making them load the classes explicitly in code)

Drupal 8 Specific Way

  • Incorporates the class loader from the Composer
    • based on the PSR-0 and PSR-4 standards, and PHP namespaces.
  • How does it work
    • Classes are declared to be in a PHP namespace with a PHP namespace declaration
    • Drupal uses namespaces beginning with the name \Drupal ,
      • Namespace(s) for a specific module mymodule should begin with \Drupal\mymodule
    • Files that depend on classes outside their own namespace have PHP use declarations for the outside classes
    • Each class declaration is in its own file
    • Drupal tells Symfony(to it's class loading system) about its namespace and directory conventions
      • for instance: look only in enabled modules' src dirs (omit those disabled)
    • If needed, class is defined via Symfony class loader, which automatically locates and loads the related include file
    • The directory that each class file goes in depends on its namespace (examples in the next slide)

Dirs and namespaces, Examples

Relations between dirs and namespaces

  • Add-on module’s class
'\Drupal\mymodule\subnamespace\Foo' 
    will go in file in dir
'mymodule/src/subnamespace/Foo.php'
  • 'core/lib' dir for core (but not part of specific D8 core module)
class '\Drupal\Component\Datetime\DateTimePlus'
    lives in file 
'core/lib/Drupal/Component/Datetime/DateTimePlus.php'
  • 'vendor/*' - classes adopted from outside projects
class '\Symfony\Component\DependencyInjection\Container'
    lives in file
'vendor/symfony/dependency-injection/Container.php'

Drupal 8 OOP Examples (Not Yet In D9, works only in D8)

Modules to enable: oop_examples, oop_design_patterns

Exercise:

Drupal Rules, Programming

  • Alterability
  • Separation of: Content, Configuration, State Data
  • i18n (internationalization)
  • Accessibility, Usability
  • DB Independency (database)
  • Security (all user-provided input is insecure)
  • Tests, Documentation

Alterability

  • Drupal core and contributed modules are almost fully alterable
    • they provide mechanisms that you can use to customize and add to their behaviour and output
  • The basic idea is that instead of editing downloaded code, you should create an add-on module or theme, which uses the existing alteration mechanisms
  • Drupal Alteration Mechanisms
    • Hooks
    • Plugins
    • Dependency Injection
    • Symfony-based routing
    • YAML-based menu

Drupal Hooks

  • PHP file or function you can put into a module or theme
  • Will be invoked (called or included) at an appropriate time by a Drupal core or contributed module
    • in order to let your module or theme alter (or add to) behaviour and output
  • Types: generic hooks, alter hooks, theme hooks (they use theme functions or template files .html.twig)
  • Theme hooks: theme preprocessing hooks and theme processing hooks

Modules to enable: Examples for Developers, Hooks example

Exercises:

Drupal Plugins

  • Replaced many of the generic hooks from Drupal 7 with an object-oriented system
    • modules can add classes that define additions to Drupal behavior

Modules to enable: Examples for Developers, Plugin type example

Exercises:

Drupal Dependency Injection

  • Allows modules to replace fundamental core systems of Drupal (or services)
    • for example the mechanism for storing cached data

Drupal Routing

  • Symfony-based routing system
    • allows modules to define URLs and their output by defining routes and controllers
    • allows to alter what happens at various points during an HTTP request by defining event subscribers

Drupal Links

  • YAML-based system
  • For defining
    • default menu links
    • contextual links
    • and related data for the menu system

Drupal Module Themeable, Output

  • Render arrays should be returned from all functions that return output
    • these will be rendered by calls to internal functions
    • the 'theme()' function does not exist in Drupal 8 for modules to call directly
    • calling 'drupal_render()' directly is also discouraged

https://training-course-material.com/training/Drupal_8_Themes

https://www.drupal.org/node/2216195

render_example

theming_example

Separation of: Content, Configuration, State Data

  • Content - Entities, Bundles, Fields, data in db
  • Configuration - setups, YAML files, definitions
  • State - stored in db, per system, temporary (dies with db)
    • in D7 handled by variables
    • common keys examples: system.cron_last, install_time
    • $pairs = \Drupal::state()->getMultiple($keys);
    • Related docs

i18n (internationalization)

Accessibility, Usability

DB Independence (database)

Security (all user-provided input is insecure)

Tests, Documentation

  • Should we bother at all, huh?
    • Yes, everything should be tested
    • Yes, everything should be documented

Everything should be tested

  • SimpleTest, PHPUnit - both adopted in D8, 1st deprecated (new tests should be written with 2nd)
  • All new changes in core must pass all of existing automated tests
  • All new core functionalities or bug-fixes must have new tests
  • Adopted also by lots of contributed modules (to some extent, at least)

Everything should be documented

  • standards for in-code documentation
    • each distinct code item (function, class, file, method, etc.) should include a documentation header
    • later these documentation headers are parsed to create the Drupal API reference site (api.drupal.org)
  • No change should be committed without its accompanying documentation being complete,
    • critical-priority bug if documentation omitted
  • Write README files, API documentation, and end-user documentation
    • prevention for next users (of course also for us, The Blessed Creators) to 'know how'
      • and 'Do Not Ask Over and Over The Same Boring Questions' (that's the lighter version, for sure!)

Drupal Mistakes, Programming

  • Programming Too Much
  • Over-Executing Code
  • Saving PHP Code in the Database
  • Working Alone

Programming Too Much

  • Avoiding Custom Programming with Fielded Data
  • Defining Theme Regions for Block Placement

Over-Executing Code

  • Executing Code on Every Page Load
  • Using an Overly General Hook

Saving PHP Code in the Database

  • It's hacking
    • Security risk
    • Risk of bugs
    • Hard to debug
    • Hard to track

Alternatives for php code in db

  • Control block visibility
    • Use Context or Layout Builder modules, which allow much more flexibility on block placement
  • Database queries
    • Use Views core module
  • Custom page or block output
    • Create your block or page in a module
  • Change how something is displayed
    • Override a theme function or template
  • Calculations for a field
    • Create your own custom field or formatter

Working Alone

  • Participating in Groups and IRC
  • Reporting Issues and Contributing Code to the Drupal Community
  • Contributing to the Drupal Community in Other Ways

Programming Examples

  • Module skeleton
  • Registering for URLs and Displaying Content
  • Using the Drupal Form API
  • Programming with Ajax in Drupal
  • Programming with Entities and Fields

Module skeleton

Exercises:

Registering for URLs and Displaying Content

  • Registering for a URL in Drupal 8
    • mm.routing.yml, HiUnivController.php, mm.permissions.yml
  • Providing administrative links
    • mm.links.menu.yml, mm.links.task.yml, mm.links.action.yml
    • to alter: hook_menu_links_discovered_alter(), hook_menu_local_tasks_alter(), hook_menu_local_actions_alter(), hook_menu_local_tasks()
  • Altering Routes and Providing Dynamic Routes in Drupal 8
    • mm.services.yml, mmRouting.php, mm.info.yml
  • Registering a Block in Drupal 8
  • Creating Render Arrays for Page and Block Output
  • Generating paged output

Page callback, menu link

Related D8 api/doc references:

Drupal 8 Interconnections example:

Modules to enable: Examples for Developers, Page example

Exercises:

Block, plugin, annotation

Related D8 api/doc references:

Modules to enable: Examples for Developers, Block Example

Exercises:

Using the Drupal Form API

  • Form Arrays, Form State Arrays, and Form State Objects
  • Basic Form Generation and Processing in Drupal 8
  • Creating Confirmation Forms
  • Adding Auto-Complete to Forms
  • Altering Forms

Programming with Ajax in Drupal

  • Setting Up a Form for Ajax
  • Wrapper-based Ajax Callback Functions
  • Command-based Ajax Callback Functions in Drupal 8

Form, validation, submit, ajax

Modules to enable: Examples for Developers, Form API Example

Exercises:

Programming with Entities and Fields

  • Terminology of Entities and Fields
  • Defining a Content Entity Type in Drupal 8
  • Defining a Configuration Entity Type in Drupal 8
  • Querying and Loading Entities in Drupal 8
  • Defining a Field Type
  • Programming with Field Widgets
  • Programming with Field Formatters

Entity, field

Modules to enable: Examples for Developers, Config entity example, Content Entity Example, Field Example, Field Permission Example

Exercises:

Programming Tools and Tips

  • Where to Find More Information
    • Drupal Site Building and General Drupal Information
    • Drupal Programming Reference and Background
    • PHP Resources
    • Database Resources
    • Other Web Technology Resources
  • Drupal Development Tools Devel
  • Discovering Drupal API Functions and Classes
  • Other Programming Tips and Suggestions

Command liners

Other Useful Modules

Errors logging

Enable logging all errors (only on testing envi!):

/admin/config/development/logging

Edit settings.php and add at the end of it:

/**
 *
 * Enable all errors reporting
 *
 */
error_reporting(E_ALL);
ini_set('display_errors', TRUE);
ini_set('display_startup_errors', TRUE);

Exercises

1. Create your own module

Make new folder modules/custom_

1.1. Config file

  1. Make another directory and name it custom_/mm (shortcut from 'my module')
  2. Provide some metadata about the project
    • Create file mm/mm.info.yml
    • Add entries in mm.info.yml as shown below
      # Required 1 line
      name: My Own Module
      # 2 optional lines
      description: Here I will learn how to code with Drupal 8
      package: Custom
      
      # Required 2 lines
      type: module
      core: 8.x
      
      # Version number. If not private module, then it will be added automatically by the packager on drupal.org
      version: VERSION
      
  3. Install the module
    • What now? How can we fix it? (-:

1.2. Module file and access granting

  1. Create file mm/mm.module
    • Put this code into it
      <?php
      
      /**
       * @file
       * My own module.
       *
       * This file can be omitted if we do not need to define any functions or implement hooks
       *
       */
      
  2. Add file for permissions mm/mm.permissions.yml
    # Permission example
    administer mm:
      title: 'Administer mm settings'
      description: 'If we really need more descriptions'
    
  3. Clear caches - or not (=
    • Do we have to clear them now? Why?

1.3. Add WARNING description to permission from the previous exercise

  1. Use d8 api website to find the solution
    • ..or search your drupal web folder (-;


2. Add simple page and link in menu

Controller

  1. Create file mm/src/Controller/HiUnivController.php
    <?php
    
    namespace Drupal\mm\Controller;
    
    use Drupal\Core\Controller\ControllerBase;
    
    class HiUnivController extends ControllerBase {
    
      /**
       * Display the markup.
       *
       * @return array
       */
      public function hiuniv() {
        return array(
          '#type' => 'markup',
          '#markup' => $this->t('Hi, Universe!'),
        );
      }
    }
    

Router

  1. Another file /mm/mm.routing.yml
    mm.hiuniv:
      path: '/hiuniv'
      defaults:
        _controller: '\Drupal\mm\Controller\HiUnivController::hiuniv'
        _title: 'Hi Universe'
      requirements:
        _permission: 'access content'
    

Menu link

  1. Almost there /mm/mm.links.menu.yml
    mm.admin:
      title: 'Hi universe simple page example'
      description: 'My module settings - link to hiuniv page'
      parent: system.admin_config_development
      route_name: mm.hiuniv
      weight: 99
    

Clearing Caches, playing around

  1. Why do we have to clear it now?
  2. What about the path, do you see anything interesting about it?
    • Change it accordingly to other links in that section - clear caches again, what do we see now (or how) and why?


3. Drupal 8 OOP specifics

The module with examples works only in D8, not yet in D9

In D9+ download the module only and don't install it

3.1. Class

  1. Create simple module which will prepare OO skeleton for 3 specific "real life" things from your company/website, etc
    • Use example 04 or 05
    • Example of business scenario:
      NobleProg Services
        Training
        Consultancy
      

3.2. Subclass with properties

  1. Extend the module from 3.1.
    • Use example 06 and 07
    • Example of business scenario:
      • Define some static properties for one of your classes
        Training
          Venue
          Number of delegates
        
      • Provide a method to wrap one property within a string
        Number of delegates 
          "There will be 6 people on this training"
        

3.3. Interface

  1. Extend the module from 3.2.
    • Use example 08 and 09
    • Example of business scenario:
      • Define the interface and getProperty() method (replace the Property with your business property name)
          getVenue();
        
      • Implement getProperty() method in both classes, one should return literal value, second should use property's value
        Training
          getVenue() { ... }
        Consultancy
          getVenue() { ... }
        


4. Make your own drupal block

Plugin

  1. New file /mm/src/Plugin/Block/HiUnivBlock.php
    <?php
    namespace Drupal\mm\Plugin\Block;
    
    use Drupal\Core\Block\BlockBase;
    
    /**
     * Provides a 'Hi Universe' Block.
     *
     * @Block(
     *   id = "hiuniv_block",
     *   admin_label = @Translation("Hi Universe block"),
     * )
     */
    class HiUnivBlock extends BlockBase {
    
      /**
       * {@inheritdoc}
       */
      public function build() {
        return array(
          '#markup' => $this->t('Hi, Universe!'),
        );
      }
    }
    

Clearing Caches

  1. What about now? Does it work straight away or not? Why?


5. Alter route, dynamic route

Router

  1. New file /mm/src/Routing/mmRouting.php
    <?php
    
    /**
     * @file
     * Contains \Drupal\mm\Routing\mmRouting.
     */
    
    namespace Drupal\mm\Routing;
    
    use Drupal\Core\Routing\RouteSubscriberBase;
    use Symfony\Component\Routing\Route;
    use Symfony\Component\Routing\RouteCollection;
    
    /**
     * Provides dynamic route and route alter.
     *
     */
    class mmRouting extends RouteSubscriberBase {
      /**
       * {@inheritdoc}
       */
      protected function alterRoutes(RouteCollection $collection) {
        // Alter the title of the mm module page (drupal/hiuniv).
        $route = $collection->get('mm.hiuniv');
        $route->setDefault('_title', 'Altered title');
    
        // Add a dynamic route at 'hiuniv/mm'
        $path = $route->getPath();
        // Constructor parameters: path, defaults, requirements
        // like in a routing.yml file.
        $newroute = new Route($path . '/mm', array(
            '_controller' => '\Drupal\mm\Controller\HiUnivController::hiuniv',
            '_title' => 'New page title',
          ), array(
            '_permission' => 'administer_mm',
          ));
    
        $collection->add('mm.newroutename', $newroute);
      }
    }
    

Service

  1. New file /mm/mm.services.yml
    # Service definitions for module.
    services:
      # Machine name of the service.
      mm.mm_routing:
        # Class providing the service.
        class: Drupal\mm\Routing\mmRouting
        # Service tags. This service is an event subscriber.
        tags:
        - { name: event_subscriber }
    

Final steps

  1. What about caches, huh?
  2. Do we follow here all the best practices?
    • Correct what should be fixed, please (=
      • Hint: router file can be better (-;
      • Don't forget to change the service too (---;
      • Reference: use 'token' module
  3. Play with dynamic parameter ../mm


6. Create own form

Extend the mm module

Use drush gen form command, but only to see it's example in the command line

  • do it with --dry-run option

6.1. Provide class form

  1. New file /mm/src/Form/mmForm.php
    <?php
    /**
    * @file
    * Contains \Drupal\mm\Form\mmForm.
    **/
    namespace Drupal\mm\Form;
    
    use Drupal\Core\Form\FormBase;
    use Drupal\Core\Form\FormStateInterface;
    
    class mmForm extends FormBase {
      /**
      * {@inheritdoc}
      */
      public function getFormId() {
        return 'mm_mm_form';
      }
    
      /**
      * {@inheritdoc}
      */
      public function buildForm(array $form, FormStateInterface $form_state) {
        // Return array of Form API elements.
        $form['franchisee_name'] = array(
          '#type' => 'textfield',
          '#title' => $this->t('Franchisee name'),
        );
    
        $form['submit'] = array(
          '#type' => 'submit',
          '#value' => $this->t('Save'),
        );
    
        return $form;
      }
    
      /**
      * {@inheritdoc}
      */
      public function validateForm(array &$form, FormStateInterface $form_state) {
        // Validation required to satisfy interface
      }
    
      /**
      * {@inheritdoc}
      */
      public function submitForm(array &$form, FormStateInterface $form_state) {
        // Submit required to satisfy interface
      }
    
    }
    
  2. Update router /mm/mm.routing.yml
    mm.form:
      path: '/mm-form'
      defaults:
        _title: 'mm form'
        _form: '\Drupal\mm\Form\mmForm'
      requirements:
        _access: 'TRUE'
    
  3. Update links /mm/mm.links.menu.yml
    mm.form:
      title: 'Hi universe form'
      description: 'My own form'
      route_name: mm.form
    

Final bits

  1. Does it work? Why (the usual)? (=
  2. Rewrite it into mm.links.task.yml. How?
    • Hint: Use pathauto module as a reference

6.2. Validate the form

Check if not empty and if it is less than 3 characters

6.3. Submit handler

Handle form submission

  1. Use messenger() and put Franchisee name in message via replacement variable (for example @frname) in t() function

6.4. Altering the form

Alter mm form with new email field ( use proper hook: hook_form_FORM_ID_alter() )


7. Custom Plugin

  1. Create a new plugin type that will work with units of measurement and conversions (ft to m, etc)
    • Discuss the best way to solve it (-:
  2. Create a new plugin type related to your business
    • You need: plugin manager, plugin interface, base class, and plugin definition.
    • Implement it


8. Custom Field

  1. Fix me - in samples/licence_plate example
    • Add licence plate custom field to Article content type
    • Add new content of Article type
    • Data is not saved for some reason - find out why
      • In the section Manage form display (admin/structure/types/manage/article/form-display)
      • HINT: use link core field to answer that (-:
    • In the section Manage display (admin/structure/types/manage/article/display)
      • There is no cog button there - fix it (How?)
      • There is also missing short summary of format settings - add it
      • HINT: use comment core field to find the answers (-:
  2. New file /mm/src/Plugin/Field/FieldType/RealName.php
    <?php
    /**
     * @file
     * Contains \Drupal\mm\Plugin\Field\FieldType\RealName.
     */
    
    namespace Drupal\mm\Plugin\Field\FieldType;
    
    use Drupal\Core\Field\FieldItemBase;
    use Drupal\Core\Field\FieldStorageDefinitionInterface;
    use Drupal\Core\TypedData\DataDefinition;
    
    /**
    * Plugin implementation of the 'realname' field type.
    *
    * @FieldType(
    *   id = "realname",
    *   label = @Translation("Real name"),
    *   description = @Translation("This field stores a first and last name."),
    *   category = @Translation("General"),
    *   default_widget = "string_textfield",
    *   default_formatter = "string"
    * )
    */
    class RealName extends FieldItemBase {
    
    
      /**
       * {@inheritdoc}
       */
      public static function schema(\Drupal\Core\Field\FieldStorageDefinitionInterface $field_definition){
        return array(
          'columns' => array(
            'first_name' => array(
              'description' => 'First name.',
              'type' => 'varchar',
              'length' => '255',
              'not null' => TRUE,
              'default' => '',
            ),
            'last_name' => array(
              'description' => 'Last name.',
              'type' => 'varchar',
              'length' => '255',
              'not null' => TRUE,
              'default' => '',
            ),
          ),
          'indexes' => array(
            'first_name' => array('first_name'),
            'last_name' => array('last_name'),
          ),
        );
      }
    
      /**
       * {@inheritdoc}
       */
      public static function propertyDefinitions(\Drupal\Core\Field\FieldStorageDefinitionInterface $field_definition) {
        $properties['first_name'] = \Drupal\Core\TypedData\DataDefinition::create('string')->setLabel(t('First name'));
        $properties['last_name'] = \Drupal\Core\TypedData\DataDefinition::create('string')->setLabel(t('Last name'));
    
        return $properties;
      }
    
    }
    

Add new field of type RealName to Article content type

  • Create content Article - what can we say?
  • Fix it!
    • Hint: compare it with code from field_example


9. Hooks

  1. Write our custom hook_help()
    • HINT: use token module as a reference
  2. Add custom token from our module
    • HINT1: use hook_token_info() and hook_tokens()
    • HINT2: use one of hook_token_info() implementations described in it's docs