KEMBAR78
Drupal8 for Symfony Developers (PHP Day Verona 2017) | PDF
Drupal8 for Symfony
Developers
Antonio Perić-Mažar

12.05.2017 @ #phpday
@antonioperic
About me
• Antonio Perić-Mažar, mag. ing. comp.
• CEO, Co-Founder @ Locastic
• Co-Founder @ Shift Conference
• Software developer, Symfony2
• Open Source Contributor
• SFUGCRO

• www.locastic.com
• antonio@locastic.com
• @antonioperic
@antonioperic
Locastic
• We help clients create amazing web and mobile apps (since 2011)
• design and development agency
• mobile development
• web development
• UX/UI
• Training and Consulting
• Shift Conference, Symfony Croatia
• www.locastic.com
• @locastic
@antonioperic
Almost 25% of our
team are women
@antonioperic
Questions?
• Any Drupal experts/developers here?
• Symfony developers?
• Symfony developers without Drupal knowledge
@antonioperic
Drupal 101 for SF
developers
@antonioperic
Before we start, small
disclaimer
@antonioperic
My world is Symfony (still)
@antonioperic
♥
@antonioperic
@antonioperic
What this means
• Drupal8 doesn’t use full stack Symfony, it uses components (maybe in future)
• Moving Drupal to modern stack
• Building powerful CMS on top of Symfony components
• More learning for Drupal developers (OOP, Symfony, new concepts)
• Connecting two big communities
@antonioperic
Who is it for?
• Content strategist
• Site Administrators
• Content editors
• “Build stuff without writing code”
• v8.3.2
• Professional developers
• Bespoke applications
• “Make writing code easier”
@antonioperic
In Drupal 8 there's three different types of
knowledge that you're going to be using in
order to work with it effectively.
@antonioperic
@antonioperic
@antonioperic
@antonioperic
@antonioperic
Symfony2
Framework
Bundle
Symfony2
Bundles
Symfony2
CMF Bundles
Symfony2
Components
Partnered Libs
(twig, etc.)
CMF
Components
Symfony fullstack Drupal 8
Distribution
Drupal Core
Modules
Drupal Contrib
Modules
Drupal Core Libraries
Symfony2
Components
Partnered Libs
(twig, etc.)
Drupal
Components
@antonioperic
Symfony Components
• ClassLoader
• Console
• CssSelector
• DependencyInjection
• EventDispatcher
• HttpFoundation
• HttpKernel
• Process
• Routing
• Serializer
• Translation
• Validator
• Yaml
@antonioperic
• HTTP Kernel
• Request / Response
• Controllers
• Event Dispatching
• Listeners / Subscribers
Dependencyinjectioncontainer
@antonioperic
Development environment
@antonioperic
Or just use your Symfony
development environment
• PHP built-in server
• Vagrant
• Docker
• …
@antonioperic
Tools
@antonioperic
Drush
• update core and contrib
• download modules
• enable modules
• clear cache
• update db
• run cron
• import config
• export config
• create user
• change password
• one time login
• backup drupal
• restore drupal
• compile twig templates
*Type “drush” to get full list - www.drushcommands.com
@antonioperic
Drupal Console
• update core and contrib
• download modules
• enable modules
• clear cache
• update db
• run cron
• import config
• export config
• generate console command
• generate entity
• generate content type
• generate modules
• run unit test
*Type “drupal list” to get full list - drupalconsole.com/docs
@antonioperic
Installation
@antonioperic
How to install Drupal8
• Drush
• drush dl drupal
• Composer
• Download zip file
@antonioperic
Lets use composer
• drupal/drupal.
• This uses Drupal itself as a template for the new site. It is the simplest
solution but lacks additional configuration that can be helpful.



• drupal-composer/drupal-project.
• This open source project acts as a kickstarter for Composer-based Drupal
sites. It provides default configuration that otherwise needs to be added
manually.
@antonioperic
Let’s use composer
@antonioperic
Let’s use composer
composer create-project drupal/drupal
@antonioperic
Let’s use composer
composer require drupal/<modulename>
for example:
composer require drupal/token
@antonioperic
Run in browser
@antonioperic
Add some content
drupal create:nodes
@antonioperic
We have content but
something is missing
@antonioperic
WebProfiler
@antonioperic
composer require drupal/devel
@antonioperic
Under the Hood
@antonioperic
Request -> Response
@antonioperic
What happens when request
enters Drupal
1. Bootstrap configuration:
◦Read the settings.php file, generate some other settings dynamically, and store
them both in global variables and the DrupalComponentUtilitySettings singleton
object.
◦Start the class loader, that takes care of loading classes.
◦Set the Drupal error handler.
◦Detect if Drupal is actually installed. If it is not, redirect to the installer script.
2. Create the Drupal kernel.
3. Initialize the service container (either from cache or from rebuild).
4. Add the container to the Drupal static class.
5. Attempt to serve page from static page cache (just like Drupal 7).
6. Load all variables (variable_get).
@antonioperic
What happens when request
enters Drupal
7. Load other necessary (procedural) include files.
8. Register stream wrappers (public://, private://, temp:// and custom
wrappers).
9. Create the HTTP Request object (using the Symfony HttpFoundation
component).
10. Let the DrupalKernel handle it and return a response.
11. Send the response.
12. Terminate the request (modules can act upon this event).
Deeper in Drupal
End of Request
@antonioperic
Pipeline
1. After the controller returned a render array, the VIEW will be triggered by the HttpKernel, because
the controller result is not a Response, but a render array.
2. MainContentViewSubscriber is subscribed to the VIEW event. It checks whether the controller
result is an array, and if so, it guarantees to generate a Response.
3. Next, MainContentViewSubscriber checks whether the negotiated request format is supported:
1. Any format for which a main content renderer service exists (an implementation of
MainContentRendererInterface is supported.
2. If the negotiated request format is not supported, a 406 JSON response is generated, which lists
the supported formats in a machine-readable way (as per RFC 2616, section 10.4.7).
4. Otherwise, when the negotiated request format is supported, the corresponding main content
renderer service is initialized. A response is generated by calling
MainContentRendererInterface::renderResponse() on the service. That's it
@antonioperic
Main Content Renderes
• HTML: HtmlRenderer (text/html)
• AJAX: AjaxRenderer (application/vnd.drupal-ajax)
• Dialog: DialogRenderer (application/vnd.drupal-dialog)
• Modal: ModalRenderer (application/vnd.drupal-modal
@antonioperic
Routing
@antonioperic
Available “defaults” keys
• _controller

The specified method is simply called with the specified route parameters, and is
expected to return a response.
• _content

If specified, the _controller is set based on the request's mime type, and fills the
content of the response with the result of the specified method (usually a string or
render array).
• _form

If specified, the _controller is set to HtmlFormController::content, which responds with
the specified form. This form must be a fully qualified class name (or service id) that
implements FormInterface and usually extends FormBase. Indeed, form building has
also become object oriented!
• _entity_form

If specified, the _controller is set to HtmlEntityFormController::content, which
responds with the specified entity form (specified as {entity_type}.{add|edit|delete}).
@antonioperic
Available “defaults” keys
• _controller

The specified method is simply called with the specified route parameters, and is
expected to return a response.
• _content

If specified, the _controller is set based on the request's mime type, and fills the
content of the response with the result of the specified method (usually a string or
render array).
• _form

If specified, the _controller is set to HtmlFormController::content, which responds with
the specified form. This form must be a fully qualified class name (or service id) that
implements FormInterface and usually extends FormBase. Indeed, form building has
also become object oriented!
• _entity_form

If specified, the _controller is set to HtmlEntityFormController::content, which
responds with the specified entity form (specified as {entity_type}.{add|edit|delete}).
@antonioperic
Available “requirements” keys
• _permission

The current user must have the specified permission.
• _role

The current user must have the specified role.
• _method

The allowed HTTP methods (GET, POST, etc).
• _scheme

Set to https or http. The request scheme must be the same as the specified scheme. This
property is also taken into account when generating urls (Drupal::url(..)) rather than routing.
If set, urls will have this scheme set fixed.
• _node_add_access

A custom access check for adding new nodes of some node type.
• _entity_access

A generic access checker for entities.
• _format

Mime type formats
@antonioperic
Controllers
@antonioperic
Services
@antonioperic
Events / Listeners
@antonioperic
@antonioperic
Registering event subscribers
Here are the steps to register an event subscriber:
Define a service in your module, tagged with 'event_subscriber' (see the Services topic for instructions).
Define a class for your subscriber service that implements SymfonyComponentEventDispatcherEventSubscriberInterface
In your class, the getSubscribedEvents method returns a list of the events this class is subscribed to, and which methods on the class
should be called for each one. Example:
public static function getSubscribedEvents() {
// Subscribe to kernel terminate with priority 100.
$events[KernelEvents::TERMINATE][] = array('onTerminate', 100);
// Subscribe to kernel request with default priority of 0.
$events[KernelEvents::REQUEST][] = array('onRequest');
return $events;
}
@antonioperic
Building Custom Module

HelloPHPUK (HelloPHPDAY)
@antonioperic
Recap
• Symfony components are main building tool for D8
• DIC is backbone of Drupal
• DI for controllers is very easy
• Events are replacing hooks
• Building custom module is easy
• Hardest thing is to start
• This is just beginning there is a lot to learn about and from D8
@antonioperic
Thank you!
antonio@locastic.com
@antonioperic
www.locastic.com
Please rate my talk
https://joind.in/talk/2c50e

Drupal8 for Symfony Developers (PHP Day Verona 2017)

  • 1.
    Drupal8 for Symfony Developers AntonioPerić-Mažar
 12.05.2017 @ #phpday
  • 2.
    @antonioperic About me • AntonioPerić-Mažar, mag. ing. comp. • CEO, Co-Founder @ Locastic • Co-Founder @ Shift Conference • Software developer, Symfony2 • Open Source Contributor • SFUGCRO
 • www.locastic.com • antonio@locastic.com • @antonioperic
  • 3.
    @antonioperic Locastic • We helpclients create amazing web and mobile apps (since 2011) • design and development agency • mobile development • web development • UX/UI • Training and Consulting • Shift Conference, Symfony Croatia • www.locastic.com • @locastic
  • 4.
    @antonioperic Almost 25% ofour team are women
  • 5.
    @antonioperic Questions? • Any Drupalexperts/developers here? • Symfony developers? • Symfony developers without Drupal knowledge
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
    @antonioperic What this means •Drupal8 doesn’t use full stack Symfony, it uses components (maybe in future) • Moving Drupal to modern stack • Building powerful CMS on top of Symfony components • More learning for Drupal developers (OOP, Symfony, new concepts) • Connecting two big communities
  • 13.
    @antonioperic Who is itfor? • Content strategist • Site Administrators • Content editors • “Build stuff without writing code” • v8.3.2 • Professional developers • Bespoke applications • “Make writing code easier”
  • 14.
    @antonioperic In Drupal 8there's three different types of knowledge that you're going to be using in order to work with it effectively.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
    @antonioperic Symfony2 Framework Bundle Symfony2 Bundles Symfony2 CMF Bundles Symfony2 Components Partnered Libs (twig,etc.) CMF Components Symfony fullstack Drupal 8 Distribution Drupal Core Modules Drupal Contrib Modules Drupal Core Libraries Symfony2 Components Partnered Libs (twig, etc.) Drupal Components
  • 20.
    @antonioperic Symfony Components • ClassLoader •Console • CssSelector • DependencyInjection • EventDispatcher • HttpFoundation • HttpKernel • Process • Routing • Serializer • Translation • Validator • Yaml
  • 21.
    @antonioperic • HTTP Kernel •Request / Response • Controllers • Event Dispatching • Listeners / Subscribers Dependencyinjectioncontainer
  • 22.
  • 25.
    @antonioperic Or just useyour Symfony development environment • PHP built-in server • Vagrant • Docker • …
  • 26.
  • 27.
    @antonioperic Drush • update coreand contrib • download modules • enable modules • clear cache • update db • run cron • import config • export config • create user • change password • one time login • backup drupal • restore drupal • compile twig templates *Type “drush” to get full list - www.drushcommands.com
  • 33.
    @antonioperic Drupal Console • updatecore and contrib • download modules • enable modules • clear cache • update db • run cron • import config • export config • generate console command • generate entity • generate content type • generate modules • run unit test *Type “drupal list” to get full list - drupalconsole.com/docs
  • 39.
  • 40.
    @antonioperic How to installDrupal8 • Drush • drush dl drupal • Composer • Download zip file
  • 41.
    @antonioperic Lets use composer •drupal/drupal. • This uses Drupal itself as a template for the new site. It is the simplest solution but lacks additional configuration that can be helpful.
 
 • drupal-composer/drupal-project. • This open source project acts as a kickstarter for Composer-based Drupal sites. It provides default configuration that otherwise needs to be added manually.
  • 42.
  • 43.
    @antonioperic Let’s use composer composercreate-project drupal/drupal
  • 45.
    @antonioperic Let’s use composer composerrequire drupal/<modulename> for example: composer require drupal/token
  • 46.
  • 53.
  • 55.
  • 57.
    @antonioperic We have contentbut something is missing
  • 59.
  • 60.
  • 70.
  • 78.
  • 80.
    @antonioperic What happens whenrequest enters Drupal 1. Bootstrap configuration: ◦Read the settings.php file, generate some other settings dynamically, and store them both in global variables and the DrupalComponentUtilitySettings singleton object. ◦Start the class loader, that takes care of loading classes. ◦Set the Drupal error handler. ◦Detect if Drupal is actually installed. If it is not, redirect to the installer script. 2. Create the Drupal kernel. 3. Initialize the service container (either from cache or from rebuild). 4. Add the container to the Drupal static class. 5. Attempt to serve page from static page cache (just like Drupal 7). 6. Load all variables (variable_get).
  • 81.
    @antonioperic What happens whenrequest enters Drupal 7. Load other necessary (procedural) include files. 8. Register stream wrappers (public://, private://, temp:// and custom wrappers). 9. Create the HTTP Request object (using the Symfony HttpFoundation component). 10. Let the DrupalKernel handle it and return a response. 11. Send the response. 12. Terminate the request (modules can act upon this event).
  • 82.
  • 84.
    @antonioperic Pipeline 1. After thecontroller returned a render array, the VIEW will be triggered by the HttpKernel, because the controller result is not a Response, but a render array. 2. MainContentViewSubscriber is subscribed to the VIEW event. It checks whether the controller result is an array, and if so, it guarantees to generate a Response. 3. Next, MainContentViewSubscriber checks whether the negotiated request format is supported: 1. Any format for which a main content renderer service exists (an implementation of MainContentRendererInterface is supported. 2. If the negotiated request format is not supported, a 406 JSON response is generated, which lists the supported formats in a machine-readable way (as per RFC 2616, section 10.4.7). 4. Otherwise, when the negotiated request format is supported, the corresponding main content renderer service is initialized. A response is generated by calling MainContentRendererInterface::renderResponse() on the service. That's it
  • 85.
    @antonioperic Main Content Renderes •HTML: HtmlRenderer (text/html) • AJAX: AjaxRenderer (application/vnd.drupal-ajax) • Dialog: DialogRenderer (application/vnd.drupal-dialog) • Modal: ModalRenderer (application/vnd.drupal-modal
  • 88.
  • 90.
    @antonioperic Available “defaults” keys •_controller
 The specified method is simply called with the specified route parameters, and is expected to return a response. • _content
 If specified, the _controller is set based on the request's mime type, and fills the content of the response with the result of the specified method (usually a string or render array). • _form
 If specified, the _controller is set to HtmlFormController::content, which responds with the specified form. This form must be a fully qualified class name (or service id) that implements FormInterface and usually extends FormBase. Indeed, form building has also become object oriented! • _entity_form
 If specified, the _controller is set to HtmlEntityFormController::content, which responds with the specified entity form (specified as {entity_type}.{add|edit|delete}).
  • 91.
    @antonioperic Available “defaults” keys •_controller
 The specified method is simply called with the specified route parameters, and is expected to return a response. • _content
 If specified, the _controller is set based on the request's mime type, and fills the content of the response with the result of the specified method (usually a string or render array). • _form
 If specified, the _controller is set to HtmlFormController::content, which responds with the specified form. This form must be a fully qualified class name (or service id) that implements FormInterface and usually extends FormBase. Indeed, form building has also become object oriented! • _entity_form
 If specified, the _controller is set to HtmlEntityFormController::content, which responds with the specified entity form (specified as {entity_type}.{add|edit|delete}).
  • 92.
    @antonioperic Available “requirements” keys •_permission
 The current user must have the specified permission. • _role
 The current user must have the specified role. • _method
 The allowed HTTP methods (GET, POST, etc). • _scheme
 Set to https or http. The request scheme must be the same as the specified scheme. This property is also taken into account when generating urls (Drupal::url(..)) rather than routing. If set, urls will have this scheme set fixed. • _node_add_access
 A custom access check for adding new nodes of some node type. • _entity_access
 A generic access checker for entities. • _format
 Mime type formats
  • 93.
  • 99.
  • 102.
  • 103.
  • 104.
    @antonioperic Registering event subscribers Hereare the steps to register an event subscriber: Define a service in your module, tagged with 'event_subscriber' (see the Services topic for instructions). Define a class for your subscriber service that implements SymfonyComponentEventDispatcherEventSubscriberInterface In your class, the getSubscribedEvents method returns a list of the events this class is subscribed to, and which methods on the class should be called for each one. Example: public static function getSubscribedEvents() { // Subscribe to kernel terminate with priority 100. $events[KernelEvents::TERMINATE][] = array('onTerminate', 100); // Subscribe to kernel request with default priority of 0. $events[KernelEvents::REQUEST][] = array('onRequest'); return $events; }
  • 105.
  • 128.
    @antonioperic Recap • Symfony componentsare main building tool for D8 • DIC is backbone of Drupal • DI for controllers is very easy • Events are replacing hooks • Building custom module is easy • Hardest thing is to start • This is just beginning there is a lot to learn about and from D8
  • 129.