Download pptx - Drupal 8 meets to symphony

Transcript

DRUPAL 8 MEETS TO SYMPHONY

.

Braham Pal Singh| Jan 19, 2015Senior consultant, Capgemini Bangalore

HttpFoundation and HTTPKernal

The HttpFoundation Component defines an object-oriented layer for the HTTP specification.

The deepest level is the HttpFoundation component. HttpFoundation provides the main objects needed to deal with HTTP. It is an object-oriented abstraction of some native PHP functions and variables:

The Request class abstracts the main PHP global variables like $_GET, $_POST,$_COOKIE, $_FILES, and $_SERVER;

The Response class abstracts some PHP functions like header(), setcookie(), and echo;The Session class and SessionStorageInterface interface abstract session management

session_*() functions.

It provides an abstraction for requests, responses, uploaded files, cookies, sessions, ...

The HttpKernel Component provides a structured process for converting a Request into a Response by making use of the event dispatcherRequest exampleuse Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; $request = Request::createFromGlobals(); echo $request->getPathInfo();

HttpFoundation and HTTPKernal cont..

Response example$response = new Response('Not Found', 404, array('Content-Type' => 'text/plain'));$response->send();

The HttpKernel Component provides a structured process for converting a Request into a Response by making use of the event dispatcher

•On top of HttpFoundation is the HttpKernel component. HttpKernel handles the dynamic part of HTTP

•It is a thin wrapper on top of the Request and Response classes to standardize the way requests are handled

•The HttpKernel class is the central class of Symfony and is responsible for handling client requests. Its main goal is to "convert" a Request object to a Response object.

•HttpKernel notifies events to convert a Request object to a Response one.

HttpFoundation and HTTPKernal cont..

EventDispatcherThe EventDispatcher component provides tools that allow your application components to communicate with each other by dispatching events and listening to them

Consider the real-world example where you want to provide a plugin system for your project. A plugin should be able to add methods, or do something before or after a method is executed, without interfering with other plugins. This is not an easy problem to solve with single inheritance, and multiple inheritance (were it possible with PHP) has its own drawbacks.

ExampleOnce a Response object has been created, it may be useful to allow other elements in the system to modify it (e.g. add some cache headers) before it's actually used.

kernel throws an event - kernel.response. Here's how it works:

•A listener (PHP object) tells a central dispatcher object that it wants to listen to the kernel.response event;•At some point, the Symfony kernel tells the dispatcher object to dispatch the kernel.response event, passing with it an Event object that has access to the Response object;•The dispatcher notifies (i.e. calls a method on) all listeners of the kernel.response event, allowing each of them to make modifications to the Response object.

EventDispatcher cont…Concrete implementation

kernel.requestDispatched as soon as the request arrives. If any listener return a Response object, all other listeners won’t be called. kernel.controllerOnce the controller is resolved, this event is dispatched and allows changing it. kernel.viewDispatched only if the controller does not return a Response. Its goal is to build a Response object from the return value of the Controller - for example, a string -. kernel.responseAllows to modify or replace the Response object after its creation – for example, adding the Google Analytics tracker code to every page -. kernel.terminateDispatched once the Response has been sent. Can be used to run expensive post-response jobs, such as sending mails or processing data. kernel.exceptionLast chance to convert an Exception into a Response object.

ClassLoader The ClassLoader Component loads your project classes automatically if they follow some standard PHP conventions.

This gives you a way to upload all your PHP classes so that the files where the classes are defined are only loaded on demand when needed.

ClassLoader can load any class as long as you follow the naming conventions

This loads project classes right when they are needed, if they are named and set up in directories that follow PHP’s PSR-4 interoperability principles.

This will help module developers out in a major way; there will be less worrying about module_load_include and similar dancing around to include dependencies, and more calling up classes at runtime to get things done.

ClassLoader cont…PSR-4 StandardExample vegetable.module directory structure:modules/vegetable/

css/js/src/

Controller/ VegetableController.php → class Drupal\vegetable\Controller

Form/ VegetableForm.php → class Drupal\vegetable\Form

Entity/ Tomato.php → class Drupal\vegetable\Entity\TomatoCucumber.php → class Drupal\vegetable\Entity\Cucumber

VegetableManager.php → class Drupal\vegetable\VegetableManagertemplates/tests/

src/ Entity/

TomatoTest.php → class Drupal\Tests\vegetable\Entity\TomatoTestCucumberTest.php → class Drupal\Tests\vegetable\Entity\CucumberTest

VegetableManagerTest.php → class Drupal\Tests\vegetable\VegetableManagerTest

fixtures/ weather-data.json

vegetable.info.ymlvegetable.routing.ymlvegetable.module

ClassLoader cont…Explanation:Each module has a namespace that corresponds to its module name.

Here: Drupal\vegetable\ The module's namespace is mapped to the ./src/ folder in the module directory.

Here: Drupal\vegetable\ → modules/vegetable/src/ Anything after the module namespace directly maps to the directory and file structure in the ./src/ folder.

Here: Drupal\vegetable\Entity\Tomato → modules/vegetable/src/Entity/Tomato.php The identical logic applies to PHPUnit tests contained in ./tests/src/.  Base namespace Base directory Contains

Drupal core Drupal\Component\core/lib/Drupal/Component/

Components that are reusable outside of Drupal.

  Drupal\Core\core/lib/Drupal/Core/

Components that are specific to Drupal.

  Drupal\Tests\core/tests/Drupal/Tests/

PHPUnit tests of core components.

ModulesDrupal\$modulename\

modules/$modulename/src/

Main integration files.

 Drupal\$modulename\Tests\

modules/$modulename/src/Tests/

Simpletest tests of the module.

  Drupal\Tests\$modulename\

modules/$modulename/tests/src/

PHPUnit tests of the module.

YAMLIt parses YAML strings and converts them to PHP arrays and vice versa

YAML is a human readable data serialization format. YAML can be used in place of XML or JSON. It provides a much more human readable format whilst still being powerful and performant.

This format has been especially designed to hold configuration related information, while being as expressive as XML files and as readable as INI files.

It allows our modules to initially define their default configuration settings and later allows the site builder to override the same as-and-when instructed to

Configuration management means moving between development, staging, and production environments incredibly easy. This gives developers the freedom to work away from production and yet within a similar environment

RoutingAllows us to load all routes, and dumps a URL matcher or generator specific to these routes. This also means that it maps an HTTP request to a set of configuration variables. As far as Drupal 8 and above versions are concerned, we define our module’s routes in a YAML configuration file, each of them set to trigger a specific action that has been defined in our module’s classes.

RoutingExampleexample.content:  path: '/example'   defaults:     _controller: '\Drupal\example\Controller\ExampleController::content'

    custom_arg: 12 

<?php  // ...  public function content(Request $request, $custom_arg) {    // Now can use $custom_arg (which will get 12 here) and $request.  }?>

DependencyInjectionDrupal 8 introduces the concept of services to decouple reusable functionality and makes these services pluggable and replaceable by registering them with a service container

Services are used to perform operations like accessing the database or sending an e-mail.

Rather than use PHP's native MySQL functions, we use the core-provided service via the service container to perform this operation so that our code can simply access the database without having to worry about whether the database is MySQL or SQLlite or if the mechanism for sending e-mail is SMTP

language_manager:    class: Drupal\Core\Language\LanguageManager    arguments: ['@language.default']  ...  path.alias_manager:    class: Drupal\Core\Path\AliasManager    arguments: ['@path.crud', '@path.alias_whitelist', '@language_manager']

A service container (or dependency injection container) is a PHP object that manages the instantiation of services.

A service container (or dependency injection container) is a PHP object that manages the instantiation of services.

DependencyInjection cont…<?php// Returns a Drupal\Core\Database\Connection object.$connection = \Drupal::database();$result = $connection->select('node', 'n')  ->fields('n', array('nid'))  ->execute();?>

Comparing Drupal 7 global functions to Drupal 8 servicesLet's take a look at the code required to invoke a module's hook as an example of the differences between Drupal 7 and 8. In Drupal 7, you would use module_invoke_all('help') to invoke all hook_help() implementations. Because we're calling the module_invoke_all() function directly in our code, there is no easy way for someone to modify the way Drupal invokes modules without making changes to the core function.

In Drupal 8, the module_* functions are replaced by the ModuleHandler service. So in Drupal 8 you would use \Drupal::moduleHandler()->invokeAll('help'). In this example, \Drupal::moduleHandler() locates the registered implementation of the module handler service in via the service container and then calls the invokeAll() method on that service.Advantages1) it allows a Drupal distribution or hosting provider or another module to

override the way invoking modules works by changing the class registered for the module handler service with another

2) The dependencies of code are also better documented3) the services can be unit tested

Twig• 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 in by *.html.twig template files.

• Unlike PHPTemplate which was developed in-house by Drupal developers, Twig comes from the wider PHP world.

Why Twig in Drupal 8?1) Multiple Data Printing Ways –

In older Drupal 7, there were two ways to print the variable. User could either use the print keyword to print some variable and render keyword to display other objects. It was difficult for user to decide what whether to print the variable via print or render.

Solution: In TWIG, this problem has been resolved and user just needs to use a pair of curly brackets before and after the variable like {{ variable }} and TWIG takes care of whether to print it or render it.Ex : Drupal 8 will access all variables consistently, for example {{ node.nid }} and {{ node_url }}2) Mixed Data Types

In Drupal 7, data types in the templates could be arrays, strings or objects and user had no clue about the type of the variable being used.

Solution: In TWIG, “dot” operator can be used to dig into the variable and the correct data type inside the variable can be accessed using the dot operator.

Twig cont…Why Twig in Drupal 8?

3) Multiple Ways to Override the MarkupCurrently in Drupal 7, there are two ways to override the markup that

comes with Drupal 7. Either copy the template in file system and change the markup or use the PHP Theme functions in order to override the markup.

Solution: In TWIG, all of the PHP theme functions will be replaced by TWIG templates therefore there will be no need to us verbose and complex PHP theme functions.4) No Reusability

In Drupal 7, there are multiple theme functions and templates performing nearly the same function due to lack of any design pattern and standard rules.

Solution: TWIG introduces patterns and standard set of rules which govern front end developers to use the already available theme and function rather than developing everything from the scratch.

5) SecurityDrupal is not secure, using node object, a user can access any

variably by digging deep into several levels of a variable which can be an object or data structure. This access to complex algorithms makes Drupal 7 vulnerable.

Solution: TWIG hides this complex and internal information from the user. In Drupal 8, users will just have to give something like a print command and TWIG will take care of all the internals issues. User will have no direct access to executable PHP template functions.

Twig cont…Why Twig in Drupal 8?

6) Language and Syntax IndependenceThe theme engine used by Drupal 7 is Drupal Specific. All the terms

and languages are not used outside Drupal. This makes it difficult for new developers to find their feet in Drupal community.

Solution: Twig is syntactically more similar to existing web languages on web such as HTML. A new user will find it easier to get use to the Drupal 8 development syntax.

Twig cont…Example

<?php print $title_attributes; ?> has been replaced by {{ title_attributes }}

<?php print $node_url; ?> has been replaced by {{ node_url }}

<?php print render($title_suffix); ?> has been replaced by {{ title_suffix }}

Serializer• Turns objects into a specific format(eg. XML, YAML, JSON,

etc.), and vice-versa. This will be used for all sorts of things, from configuration to preparing nodes & entities for delivery by a REST endpoint.

Serializer cont…Serilization sample code$serializer = \Drupal::service('serializer'):

$output = $serializer->serialize($entity, $format);

Deserilization sample code$client = \Drupal::service('http_client');

$result = $client->get('http://example.com/entity/node/1', ['Accept' => 'application/json']); $output = $result->getBody(); $serializer = \Drupal::service('serializer'):

$entity = $serializer->deserialize($output, 'Drupal\node\Entity\Node', $format);

The component is used to make drupal 8 available for REST API.

This allows you to use all the Drupal 8 features to edit your content but present the content not only on a Drupal frontend but also on mobile apps or anything else that can work with JSON data.

ValidatorWith the Validator component Drupal will validate values in a general sense. For example, form submissions or validating entities within Drupal. The Validator uses Doctrine Annotations for its function.

Enables specifying validation rules for classes using XML, YAML, PHP or annotations, which can then be checked against instances of these classes. 

In Drupal 8 Entity validation is moved to a separate Entity validation API and decoupled from form validation. Decoupling entity validation from forms allows validation entities to be independent from form submissions, such as when changed via the RESTful web service. This new validation API has been implemented based on the Symfony validator.

1) Entities can be validated seperately2) Validation can be put directly as property of field contraint3) Using the API

Translation Provides a standard set of tools to load translation files, generate

translated strings as output, and use the generated outcome.

1) Improve the developer experience of field languages considerably

2) Introduce language support for data that is not (yet) fields: title, status, author, etc.

3) Add language assignment to entities that don't currently support that: taxonomy, files, etc.

4) Introduce new content translation module based on field translation with the above improvements

5) Remove existing content translation module and provide a migration path for all existing data

6) Provide better summaries and overviews of translation status on core administration pages

Assetic Assetic is a PHP library for asset management An Asset Management framework. Assets in Drupal consist of CSS

files, JavaScript files, images, other media files, metadata, etc. This will effectively take on the duty of compressing CSS and

JavaScript, managing image styles, and dealing with other media types in a consistent fashion.

Assetic in Drupal• Drupal assets• Asset bags. Have a lot of assets to declare? Drop them into a bag.

Bags are a way to pass around assets through the Drupal system• Dependancies work much better than weights. If a js file depends

on jQuery it will not be loaded before jQuery.• drupal_add_css(), and drupal_add_js() - gone. Better mechanisms

for declaring, organizing, and aggregating assets.

Composer A tool specifically designed and developed to manage dependency

in PHP allowing us to declare the dependent libraries our project needs and install them for us

Handles situations very efficiently wherein your project is dependent upon a number of libraries.

Tackles situations where there is a nested dependency concept amongst the libraries. For instance; your project is dependent upon a library (say, lib1) and in tern lib1 is dependent upon some other library (say, lib2).

It is Composer’s responsibility to choose which version of the package or library needs to be installed unless explicitly told which versions to target..

Composer.json looks like

"require": {

"php": ">=5.3.3",

"symfony/symfony": "2.3.*",

"doctrine/doctrine-bundle": "1.2.*", > php composer.phar require "doctrine/doctrine-bundle": "1.2.*“ > php composer.phar update

Doctrine A bundle of tools for use with database records Drupal 8 uses a part of it called Annotations that exposes

additional metadata to Drupal Annotations

This provides extra metadata to Drupal, telling it what various components are used for. This is a pretty tricky piece of functionality but it’s going to come in handy later, especially when developers need to define custom entity types.

Refactored solution• Does not need to extend a base class or to implement an interface.• Generates Physical Data Model from classes themselves.• No need for Schema API anymore in the long run.• Uses annotations the correct way.• Have a meta-data caching system included.

Doctrine cont…

Doctrine cont…

EasyRDF This library makes it easy to consume and produce RDF, which

allows Drupal 8 sites to produce metadata in the markup, preparing them to be first class citizens of the semantic web.

With the help of EasyRDF, Drupal 8 adds capability to produce metadata in the markup in an easy and convenient way.

RDF (Resource description framework) Example

Guzzle, PHPUnit,PSR3-Logging

Guzzle This is a PHP HTTP client, enabling Drupal 8 to make web requests

using REST based web service calls This makes Drupal 8 web portals more efficient in terms of

handling different sorts of web services

PHPUnit• Industry standard unit testing• Drupal uses it to make sure core works the right way all the time• helps module devs build their modules the right way• PHPUnit ensures that any code written in Drupal 8 and in any

custom module incorporated in it matches industry standards

PSR3-Logging• A common logging system that is shared by an entire PHP

application• Drupal 7 and older versions use watchdog() for this purpose• Switching Drupal logging from watchdog() to a PSR-3 logging

framework has made Drupal 8 more robust and scalable in terms of common logging

Drupal 8 folder structure/core - All files provided by core, that doesn't have an explicit reason to be in the / directory. More details futher down./libraries - 3rd party libraries, eg. a wysiwyg editor. Not included by core, but common enough to warrant inclusion here./modules - The directory into which all custom and contrib modules go.

Splitting this up into the sub-directories contrib and custom can make it easier to keep track of the modules. enough to warrant mention here.

/profile - contributed and custom profiles./themes - contributed and custom (sub)themessites/[domain OR default]/{modules,themes} - Site specific modules and themes can be moved into these directories to avoid them showing up on every site. sites/[domain OR default]/files - Site specific files tend to go here. This could be files uploaded by users, such as images, but also includes the configuration, active as well as staged config. The configuration is read and written by Drupal, and should have the minimal amount of privileges required for the webserver, and the only the webserver, to read and modify them.

Drupal 8 folder structure cont…/core/assets - Various external libraries used by Core. jQuery, etc./core/misc - Frontend libraries that Drupal Core depends on. (drupal.js, etc) /core/includes - Functionality that is to low level to be modular. Such as the module system itself./core/lib - Drupal Core classes./core/modules - Drupal Core modules./core/profiles - Drupal Core profiles. Empty at the time of writing./core/scripts - Various CLI scripts, mostly used by developers./core/tests - Drupal Core tests./core/themes - Drupal Core themes./core/vendor - Backend libraries that Drupal Core depends on. (Symfony, Twig, etc)

Drupal 8 caching• Caching is easy: it's merely storing the result of an expensive

computation, to save time the next time you need it. • Cache invalidation is hard: if you fail to invalidate all the things

that should be invalidated, you end up with incorrect results• If you invalidate too many things, your cache hit ratio is going to

suffer, and you'd be inefficiently using your caches. Invalidating only the affected things is very hard.

ExampleProblem• That has served us well, but how are you — for example — after

modifying Node 42 going to clear all cache entries containing Node 42? In the Drupal 7 API, you can't. (Because any module might generate something that depends on the data in Node 42, and the Cache API can't know what that cache ID would be.)

SolutionTo solve that problem, Drupal 8 introduced cache tags. Then any cache entry tagged with node:42 would be invalidated whenever Node 42 was modified.With cache tags, it is easier to identify multiple cache entries and invalidate them later on.

Drupal 8 caching cont…<?php$cache = cache($bin);$nid = 1;$cache->set('cache_id_one', $some_value, CacheBackendInterface::CACHE_PERMANENT, array('node:' . $nid));$cache->set('cache_id_two', $some_value, CacheBackendInterface::CACHE_PERMANENT, array('node:' . $nid));

Cache::invalidateTags(array('node:' . $nid));?>


Recommended