Feb 12 2018
Feb 12
Login or get out!

Currently we are busy constructing the production of a realtime messaging platform in Drupal and NodeJS, look at it as a ‘WhatsApp for Business’. This Drupal system works like a web app; logging in is mandatory. How do you make sure that logged out visitors must log in to Drupal 8 before they are allowed to continue?

Drupal has many out-of-the-box functionalities, as well as a powerful API, but because it has so many functions many tracks are standardly available for anonymous visitors. We’d want to make all paths unreachable, until you log in.

That means that visitors always will be redirected to the login screen as long as they aren’t logged in. You wouldn’t want an anonymous user reaching internal news on the homepage.

Redirect URL in Drupal 8

Basically, we want all url’s / paths be made unavailable for non-logged in visitors, except explicitly specified pages like:

  • Login (/user)
  • Forgot password (/user/password)
  • Login link (user/reset/login)

in Drupal 7 you could use the module Logintoboggan for that purpose. You could also easily work around it in hook_init() or hook_boot() in a custom Drupal 7 module.

Quest

This was quite a puzzle, and we soon found some examples as well as exceptions. Everytime it didn’t work how we wanted it to. This example was the most useful.

Implementation in Drupal 8

Eventually, we got it working with the help of following code in a custom Drupal 8 module:

services.yml

put this file in your module root, and format yourmodulename.services.yml:

RedirectAnonymousSubscriber.php

Put the file RedirectAnonymousSubscriber.php in folder /src/EventSubscriber/ and do your custom thing:

This code builds on symfony’s EventSubscriber, the framework on which Drupal8 has been built.

Wrap up

Alright, that’s it. I hope the information as described will help you to always redirect visitors to the login page. Questions or feedback? Let me know!

Feb 01 2018
Feb 01

As a digital agency we need to have a good content management solution for our clients. Even in situations where we are developing more custom apps than content web applications, we still need a good, modular CMS solution. As Symfony developers, we wanted to find powerful CMS solutions built on Symfony. We wanted to use our Symfony knowledge for building custom things on our chosen CMS solution. In this article, I will show you what we learned and how you can build things using Symfony inside Drupal.

This article was originally published in the February 2018 issue of php[architect] magazine. To read the complete article please subscribe or purchase the complete issue.

Sep 18 2017
Sep 18

So, like a bunch of other Drupal people, we’re also experimenting with Drupal 8; for our Drupal distro OpenLucius. Us being ‘less is more’-developers, one aspect we really like is dependency injection.

First things first, for all new developers we should explain exactly what dependency injection is. Dependency injection is an advanced software design pattern. It implements “inversion of control”, this sounds complex but it basically means that reusable code calls task specific code. (Reference: http://en.wikipedia.org/wiki/Inversion_of_control)

What does this mean for us Drupal developers?
It means we can write more efficient code by reducing the load. We only load what we need.

Types of injection

There are multiple types of Dependency injection:

  1. Constructor injection, where the dependency is injected through a class’s constructor.
  2. Setter injection, where the dependency is injected through a setter method of a class.
  3. Property injection, where a public field of a class is directly set.

All three methods have their pro’s and con’s I’ll try to explain these three in detail.

1. Constructor injection

There’s no real downside to using constructor injected dependency injections. The advantages are:

  • Constructor injection can ensure that a class cannot be constructed without a required dependency.
  • The constructor is only called once so the dependency cannot be altered afterwards

These two advantages do not limit the ability to use optional dependencies; these can be implemented using one of the other methods. It does however tend be a bit more difficult to extend the class or override the constructor.

Simple example of constructor based injection:

class SimpleClass { protected $variable; public function __construct(\SimpleType $variable) { $this->variable = $variable; } }

As you can see the SimpleType class is injected into the protected variable of the SimpleClass. Basically that’s all you have to do to :)

2. Setter injection

This type of dependency injection is often used for optional requirements as the only thing you have to do to prevent adding a dependency is not calling the setter.

The advantages are:

  • The above-mentioned, setting of optional dependencies.
  • You can call a setter method multiple times. This also allows you to add multiple dependencies using only one method.

The downsides are:

  • The setter can also be called after the construction of the object. Therefore you can’t guarantee that a dependency is not replaced.
  • You can’t be certain that a setter is called at any moment in time. So you have to implement a method to verify if a dependency is indeed injected.

Simple example of setter-injection:

class SimpleClass { protected $variable; public function setType(\SimpleType $variable) { $this->variable = $variable; } }

3. Property injection

Injecting directly into class objects is not advisable but there’s a small possibility that a thirdparty library implements public properties.

The downsides are:

  • There is no way of controlling whether a dependency is set. It can be changed at any point.
  • You can’t use type hinting to verify what type of dependency is injected. (type hinting is a way of ensuring that an object is of a certain type. For more information have a look at the phpdocs http://php.net/manual/en/language.oop5.typehinting.php)

Simple example of property injection:

class SimpleClass { public $variable; }

Dependency injection Drupal

All of this was PHP dependency injection, which can be easily implemented in Drupal 8. I’ll show two simple ways to implement these three methods, which can be downloaded as an example module at the bottom of the page. I’ll show a direct approach to using these 3 methods and a service-based approach. Both are quite simple to implement.

For demonstration purposes i’ve created simple module containing the four classes now properly named in a namespace called ‘Drupal\dep_test’ where dep_test is the name of the module. The classes are now distinguishable from each other:

  • SimpleClassConstructor
  • SimpleClassSetter
  • SimpleClassProperty
  • SimpleType

Within this module I’ve added a simple Controller, which makes it easy to display values. In the controller class I’ve added the following code for a direct approach:

// Initiate the Classes. $this->constructor = new SimpleClassConstructor(new SimpleType()); $this->setter = new SimpleClassSetter(); $this->property = new SimpleClassProperty(); // Inject dependencies. $this->setter->setType(new SimpleType()); $this->property->variable = new SimpleType();

As you can see a direct approach is quite simple to implement. Now we’re going to use a service based approach. For this we’re going to use a services.yml file.

This file contains the services and the function calls / properties to be set.

services: deptest.simple_type: class: Drupal\dep_test\SimpleType deptest.constructor: class: Drupal\dep_test\SimpleClassConstructor arguments: ['@deptest.simple_type'] deptest.setter: class: Drupal\dep_test\SimpleClassSetter calls: - [setType, ["@deptest.simple_type"]] deptest.property: class: Drupal\dep_test\SimpleClassProperty properties: variables: "@deptest.simple_type"

From top to bottom:

  • We define the simple_type service and tell, which class should be used.
  • We define the constructor service, set the class and give the simple_type class as an argument.
  • We define the setter service, set the class, set the function call and the argument for the function call.
  • We define the property service, set the class and set the property to the simple_type class.

Now if we call one of these services using the service container all properties will be set, just like the direct approach.

$this->service1 = \Drupal::service('deptest.constructor'); $this->service2 = \Drupal::service('deptest.setter'); $this->service3 = \Drupal::service('deptest.property');

Calling the service container directly is not advisable but for demonstration purposes it should suffice.

The end

That’s about it for this blog item. I hope it helps someone. Don’t forget to download the full package and have a look at the code.

Aug 17 2015
Aug 17

In the first article on Drupal 8 module development we looked a bit at the routing aspect of this process. We’ve seen that creating pages with paths is now a matter of declaring routes that match up with controllers. The latter, as we’ve seen, can return a render array that gets interpreted into markup and displayed in the main content area of that page. However, did you know that under the hood, Drupal actually transforms that array into a Response object according to the dictates of Symfony’s HTTPKernelInterface?

drupal8wide

In this article, I would like us to go deeper into the internals of Drupal 8 (and Symfony2) and look at what actually happens (and can happen) from the moment a request is made by a user to the one in which they see something returned in response. The example I mentioned above is just one direction this process can go in, and today we are also going to see other possibilities. The goal is to understand the flexibility of the system which in turn can help us build awesome applications.

Before going into it, I strongly recommend you check out this diagram which does an amazing job at synthesizing what is often referred to as the render pipeline. Though in my opinion it represents more than the name implies because the render system is only part of what’s depicted, albeit a big one.

Front controller (index.php)

It’s no secret that Symfony2 is now an important part of Drupal. The latter uses many of Symfony’s components, most importantly for this article the HTTPKernel and HTTPFoundation ones. Together they are responsible for encapsulating a user request, passing it to the application and then returning whatever comes back to the user in a consistent and OO way.

The HTTPKernelInterface (something you probably heard about also from other contexts) is what glues all of this together by taking in a Request object and always returning a Response one. A very simple but powerful concept.

This process is initiated inside the index.php file which starts by generating said Request object and passing it to the HTTPKernel::handle() method. The latter is then responsible for returning a Response object. At a high level, this is what happens both in a Drupal application as well as in a Symfony one (or any other that leverages the HTTPKernel component).

HTTPKernel and events

HTTPKernel is the heart of any Symfony based application. Its handle() method, as we saw, has a great deal of responsibility in preparing a response and it does so in a workflow driven by events. This makes for a very flexible application where the heavy lifting is always delegated to listeners of these events.

If you look at the diagram from earlier, you can see this workflow depicted in the second column, and it essentially represents the glue between Symfony and the Drupal side of things.

It starts with the first event called kernel.request. Subscribers to this event handle various tasks. But two very important ones in Drupal 8 are the format negotiation and routing. The first determines the type of response that needs to be returned (html, json, image, pdf, etc) while the second determines what the code responsible for handling this is (the _controller key of a route definition inside the routing.yml file). But like in most steps in this event workflow, if a listener returns a response object, the process skips most of the further steps (stops propagation) and goes straight to kernel.response.

The second event is kernel.controller which is called after the application knows which controller is responsible for handling the request. At this point, listeners can still perform some overriding operations on it. Closely following this step, the Kernel is responsible for resolving the arguments that get passed to the controller. One such operation in Drupal is loading objects based on IDs found in the request (for example nodes) and directly providing the controller with them. Then finally the controller gets called with the respective parameters.

The controller is responsible for returning a response of some kind. If it returns a Response object, the process skips to the kernel.response event. Listeners to the latter can perform last minute modifications on the object such as modifying headers or the content itself. And after getting it from the handle() method, the front controller uses the send() method on the Response object to send it back to the user and terminates the process.

symfony event workflow

Going deeper with render arrays

If the controller does not return a Response object, the Kernel fires one last event: kernel.view. Its subscribers are responsible for turning the result of the controller into an actual Response object. So this means that you have the option of returning from your controller any kind of object as long as you couple it with a VIEW event subscriber that turns that into a proper Response.

However, as we’ve seen in the example, most of the time controllers will return a render array. Usually this represents the page’s main content (similar to page callbacks in Drupal 7).

To handle this, Drupal 8 has a MainContentViewSubscriber responsible for transforming this array into proper Response objects. It does so by using a particular MainContentRenderer chosen during the format negotiation phase we’ve talked about before. And although there are a few such renderers already available, the default one used is the HtmlRenderer.

HTMLRenderer

Since this is the most commonly used type of main content renderer, let’s go in a bit deeper and see how this builds the page.

One of the cool things about this step in the process is the concept of page variants.
This means that HTMLRenderer dispatches an event responsible for finding out which type of page is to be used to wrap the main content render array: RenderEvents::SELECT_PAGE_DISPLAY_VARIANT. By default, the SimplePageVariant is used unless the Block module is enabled. In that case the BlockPageVariant kicks in and allows the placement of the blocks in the regions around the main content. If you want, you can subscribe to this event in your own module and provide your own variant.

All of this happens within the prepare() method of the HTMLRenderer which supplies the renderResponse() method with a #type => 'page' render array that wraps the main content one. The latter two get in turn wrapped into a #type => 'html' render array which gets finally rendered using the Renderer class (the equivalent of drupal_render() in Drupal 7). The resulting HTML string gets added to the Response object and gets returned to the front controller.

Although this is a very high level overview of the process, this is basically what happens. Now we have a Response object which means the Kernel can dispatch its kernel.response event. And right after this, the front controller can send the Response back to the user and terminate the process.

Conclusion

In this article we’ve taken a journey into Drupal 8 (and Symfony2) internals by following the pipeline from a user request to the response the server returns. We’ve seen how Drupal 8 leverages the HTTPKernel and HTTPFoundation Symfony2 components and how it basically lives on top of them. Additionally, we’ve seen how the glue between them is made up of the events the Kernel dispatches to which Drupal subscribes for all of its functionality. Finally, we’ve seen how HTML pages are built and returned to the user with the help of the render pipeline.

I believe that understanding what is going on under the hood in a Drupal 8 application will allow you to create awesome applications by knowing exactly which entry points you have into this flow. And I believe that if you take away only one thing from this article, it should be the word flexibility. Because the flexibility for building exactly what we need in Drupal 8 far surpasses anything in Drupal 7. It has truly become modern.

Feb 27 2015
Feb 27

There are thousands of situations in which you do not want to reinvent the wheel. It is a well known principle in Software Engineering, but not always well applied/known into the Drupal world.

Let’s say for example, that you have a url that you want to convert from relative to absolute. It is a typical scenario when you are working with Web (but not just Web) crawlers. Well, you could start building your own library to achieve the functionality you are looking for, packaging all in a Drupal module format. It is an interesting challenge indeed but, unless for training or learning purposes, why wasting your time when someone else has already done it instead of just focussing on the real problem? Especially if your main app purpose is not that secondary problem (the url converter).

What’s more, if you reuse libraries and open source code, you’ll probably find yourself in the situation in which you could need an small improvement in that nice library you are using. Contributing your changes back you are closing the circle of the open source, the reason why the open source is here to stay and conquer the world (diabolical laugh here).

That’s another one of the main reasons why lot’s of projects are moving to the Composer/Symfony binomium, stop working as isolated projects and start working as global projects that can share code and knowledge between many other projects. It’s a pattern followed by Drupal, to name but one, and also by projects like like phpBB, ezPublish, Laravel, Magento,Piwik, …

Composer and friends

Coming back to our crawler and the de-relativizer library that we are going to need, at this point we get to know Composer. Composer is a great tool for using third party libraries and, of course, for contributing back those of your own. In our web crawler example, net_url2 does a the job just beautifully.

Nice, but at this point you must be wondering… What does this have to do with Drupal, if any at all? Well, in fact, as everyone knows, Drupal 8 is being (re)built following this same principle (DRY or don’t repeat yourself) with an strong presence of the great Symfony 2 components in the core. Advantages? Lots of them, as we were pointing out, but that’s the purpose of another discussion

The point here is that you don’t need to wait for Drupal 8, and what’s more, you can start applying some of this principles in your Drupal 7 libraries, making your future transition to Drupal 8 even easier.

Let’s rock and roll

So, using a php library or a Symfony component in Drupal 7 is quite simple. Just:

  1. Install composer manager
  2. Create a composer.json file in your custom module folder
  3. Place the content (which by the way, you’ll find quite familiar if you’ve already worked with Symfony / composer yaml’s):
    "require": {
      "pear/net_url2": "2.0.x-dev"
     }
    
    
  4. enable the custom module

And that’s it basically. At this point we simply need to tell drupal to generate the main composer.json. That’s basically a composer file generated from the composer.json found in each one of the modules that include a composer themselves.

Lets generate that file:

drush composer-rebuild

At this point we have the main composer file, normally in a vendor folder (if will depend on the composer manager settings).

Now, let’s make some composer magic :

drush composer update

At this point, inside the vendors folder we should now have a classmap, containing amongst others our newly included library.

Hopefully all has gone well, and just like magic, the class net_url2 is there to be used in our modules. Something like :

$base = new Net_URL2($absoluteURL);

Just remember to add the library to your class. Something like:

use Net_URL2;

In the next post we’ll be doing some more exciting stuff. We will create some code that will live in a php library, completely decoupled but at the same time fully integrated with Drupal. All using Composer magic to allow the integration.

Why? Again, many reasons like:

  1. Being ready for Drupal 8 (just lift libraries from D7 or D6 to D8),
  2. Decoupling things so we code things that are ready to use not just in Drupal, and
  3. Opening the door to other worlds to colaborate with our Drupal world, …
  4. Why not use Dependency Injection in Drupal (as it already happens in D8)? What about using the Symfony Service container? Or something more light like Pimple?
  5. Choose between many other reasons…

See you in my next article about Drupal, Composer and friends, on the meantime, be good :-).

Updated: Clarified that we are talking about PHP Libraries and / or Symfony components instead of bundles. Thanks to @drrotmos and @Ross for your comments.

Oct 20 2014
Oct 20

How to Build a Drupal 8 Module

Please be aware that due to the development process Drupal 8 has been undergoing at the time of writing, some parts of the code might be outdated. Take a look at this repository in which I try to update the example code and make it work with the latest Drupal 8 release.

With the incorporation of many Symfony components into Drupal in its 8th version, we are seeing a shift away from many Drupalisms towards more modern PHP architectural decisions. For example, the both loved and hated hook system is getting slowly replaced. Plugins and annotations are taking away much of the need for info hooks and the Symfony Event Dispatcher component is replacing some of the invoked hooks. Although they remain strong in Drupal 8, it’s very possible that with Drupal 9 (or maybe 10) hooks will be completely removed.

In this article we are going to primarily look at how the Symfony Event Dispatcher component works in Drupal. Additionally, we will see also how to invoke and then implement a hook in Drupal 8 to achieve similar goals as with the former.

To follow along or to get quickly started, you can find all the code we work with here in this repository. You can just install the module and you are good to go. The version of Drupal 8 used is the first BETA release so it’s preferable to use that one to ensure compatibility. Alpha 15 should also work just fine. Let’s dive in.

What is the Event Dispatcher component?

A very good definition of the Event Dispatcher component can be found on the Symfony website:

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

I recommend reading up on that documentation to better understand the principles behind the event dispatcher. You will get a good introduction to how it works in Symfony so we will not cover that here. Rather, we will see an example of how you can use it in Drupal 8.

Drupal 8 and the Event Dispatcher

For the better part of this article, we will focus on demonstrating the use of the Event Dispatcher in Drupal 8. To this end, we will create a simple demo module (event_dispatcher_demo) that has a configuration form which saves two values as configuration. Upon saving this form, we will dispatch an event that contains the config object and which will allow other parts of the application to intercept and modify it before being saved. Finally, we will do just that by demonstrating how to subscribe (or listen) to these events.

In Drupal 7, this type of modularity is only achieved with hooks. Hooks are being invoked and modules have the option to implement them and contribute with their own data. At the end of this article, we will see how to do that as well in Drupal 8. But first, let’s get on with our demo module.

If you don’t know the basics of Drupal 8 module development, I recommend checking out my previous articles in this series.

The form

The first thing we need is a simple config form with two fields. In a file called DemoForm.php located in the src/Form folder, we have the following:

<?php

/**
 * @file
 * Contains Drupal\event_dispatcher_demo\Form\DemoForm.
 */

namespace Drupal\event_dispatcher_demo\Form;

use Drupal\Core\Form\ConfigFormBase;
use Drupal\Core\Form\FormStateInterface;

class DemoForm extends ConfigFormBase {

  /**
   * {@inheritdoc}
   */
  public function getFormID() {
    return 'demo_form';
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    $config = $this->config('event_dispatcher_demo.demo_form_config');
    $form['my_name'] = [
      '#type' => 'textfield',
      '#title' => $this->t('My name'),
      '#default_value' => $config->get('my_name'),
    ];
    $form['my_website'] = [
      '#type' => 'textfield',
      '#title' => $this->t('My website'),
      '#default_value' => $config->get('my_website'),
    ];
    return parent::buildForm($form, $form_state);
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {

    parent::submitForm($form, $form_state);

    $config = $this->config('event_dispatcher_demo.demo_form_config');

    $config->set('my_name', $form_state->getValue('my_name'))
      ->set('my_website', $form_state->getValue('my_website'));
      
    $config->save();
  }

}

Let’s also create a route for it (in the event_dispatcher_demo.routing.yml file) so we can access the form in the browser:

event_dispatcher_demo.demo_form:
  path: 'demo-form'
  defaults:
    _form: '\Drupal\event_dispatcher_demo\Form\DemoForm'
    _title: 'Demo form'
  requirements:
    _permission: 'access administration pages'

So now if you point your browser to example.com/demo-form, you should see the form. Submitting it will create and persist a configuration object called event_dispatcher_demo.demo_form_config that contains two fields: my_name and my_website .

The event dispatcher

Now it’s time to work on the form submit handler (the formSubmit() method) and dispatch an event when the form is saved. This is what the new method will look like:

public function submitForm(array &$form, FormStateInterface $form_state) {

  parent::submitForm($form, $form_state);

  $config = $this->config('event_dispatcher_demo.demo_form_config');

  $config->set('my_name', $form_state->getValue('my_name'))
    ->set('my_website', $form_state->getValue('my_website'));

  $dispatcher = \Drupal::service('event_dispatcher');

  $e = new DemoEvent($config);

  $event = $dispatcher->dispatch('demo_form.save', $e);

  $newData = $event->getConfig()->get();

  $config->merge($newData);

  $config->save();
}

So what happens here? After we take the submitted values and add them to the config object like before, we retrieve the event dispatcher object from the service container:

$dispatcher = \Drupal::service('event_dispatcher');

Please keep in mind that it’s recommended you inject this service into your class, but for brevity, we will retrieve it statically. You can read this article about dependency injection and the service container for more information.

Then we create a new DemoEvent object and pass it the $config through its constructor (we have not yet created the DemoEvent class, we will do that in a minute). Next, we use the dispatcher to dispatch an event of our type and assign this action the identifier demo_form.save. This will be used when subscribing to events (we’ll see this later). The dispatch() method returns the event object with modifications made to it so we can retrieve the config values that may or may not have been altered elsewhere and merge them into our original configuration. Finally, we save this object like we did initially.

Before moving onto the event subscription part of our application, let’s create the DemoEvent class we just instantiated above. In a file called DemoEvent.php located in the src/ folder of our module, we have the following:

<?php

/**
 * @file
 * Contains Drupal\event_dispatcher_demo\DemoEvent.
 */

namespace Drupal\event_dispatcher_demo;

use Symfony\Component\EventDispatcher\Event;
use Drupal\Core\Config\Config;

class DemoEvent extends Event {

  protected $config;

  /**
   * Constructor.
   *
   * @param Config $config
   */
  public function __construct(Config $config) {
    $this->config = $config;
  }

  /**
   * Getter for the config object.
   *
   * @return Config
   */
  public function getConfig() {
    return $this->config;
  }

  /**
   * Setter for the config object.
   *
   * @param $config
   */
  public function setConfig($config) {
    $this->config = $config;
  }

} 

As you can see, this is a simple class that extends the default Event class and which defines setters and getters for the config object we will be passing around using this event. And since we created it, let’s also make sure we use it in the file where we defined the form:

use Drupal\event_dispatcher_demo\DemoEvent;

The event subscriber

Now that our form is functioning normally and an event is being dispatched when the form is saved, we should take advantage of that and subscribe to it. Let’s start with the event subscriber class that implements the EventSubscriberInterface. Inside a file called ConfigSubscriber.php (name of your choice) located in the src/EventSubscriber/ folder, we have the following:

<?php

/**
 * @file
 * Contains Drupal\event_dispatcher_demo\EventSubscriber\ConfigSubscriber.
 */

namespace Drupal\event_dispatcher_demo\EventSubscriber;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class ConfigSubscriber implements EventSubscriberInterface {

  static function getSubscribedEvents() {
    $events['demo_form.save'][] = array('onConfigSave', 0);
    return $events;
  }

  public function onConfigSave($event) {

    $config = $event->getConfig();

    $name_website = $config->get('my_name') . " / " . $config->get('my_website');
    $config->set('my_name_website', $name_website);
  }

}

So what happens here? The EventSubscriberInterface has only one required method called getSubscribedEvents(). This method is used to register events and callbacks to these events. So above we registered the callable onConfigSave() (found in the same class below) to the event dispatched with the identifier of demo_form.save. And in the callback method we simply add another value to the config object (based on a concatenation of the existing two values). The latter part is just for our demo purposes: here you can do what you want.

When we subscribed our onConfigSave() method to listen to the demo_form.save event, we passed a weight of 0. If you register multiple callbacks to the same event, this weight becomes important (the higher the number, the earlier it gets called). And if a callback alters the same values as one triggered before, they will get overridden. It’s good to keep this in mind.

Now in order for this event subscriber to work, we need to define it as a service and give it the event_subscriber tag. So in a file called event_dispatcher_demo.services.yml found in the root folder of our module, we will have this:

services:
  event_dispatcher_demo.config_subscriber:
    class: Drupal\event_dispatcher_demo\EventSubscriber\ConfigSubscriber
    tags:
      - { name: event_subscriber }

This is a simple service definition with the right tag that will make the container automatically instantiate an object of this class whenever the dispatcher is in play. And that is pretty much it. Clear the cache and if you now save the form again, the configuration object that gets saved will always contain a new value that is based on the first two.

Hooks

In the final part of this article we will demonstrate the use of hooks to achieve a similar goal.

First, let’s change the form submit handler and instead of dispatching events, we will invoke a hook and pass the config values to it. This is what the new submitForm() method will look like:

public function submitForm(array &$form, FormStateInterface $form_state) {

        parent::submitForm($form, $form_state);
        
        $config = $this->config('event_dispatcher_demo.demo_form_config');
        
        $config->set('my_name', $form_state->getValue('my_name'))
          ->set('my_website', $form_state->getValue('my_website'));
        
        $configData = $config->get();
        $newData = \Drupal::service('module_handler')->invokeAll('demo_config_save', array($configData));
        
        $config->merge($newData);
        
        $config->save();
}

We are not using any event objects nor the dispatcher service. Instead, we retrieve the Module Handler service that contains the invokeAll() method used to invoke hook implementations from all modules. This is essentially replacing the Drupal 7 module_invoke_all() helper. And again, it is recommended to inject this service, but for brevity, we’ll retrieve it statically.

The hook implementation invoked in our case is hook_demo_config_save and it gets one parameter, an array of values pulled from our config object. Inside $newData we will have an array of values merged from all the implementations of this hook. We then merge that into our config object and finally save it.

Let’s quickly see an example hook implementation. As with Drupal 7, these can only be in .module files:

/**
 * Implements hook_demo_config_save().
 */
function event_dispatcher_demo_demo_config_save($configValues) {

  $configValues['my_name_website'] = $configValues['my_name'] . " / " . $configValues['my_website'];

  return $configValues;

}

As you can see, we are adding a new value to the config array that will later be merged into the object getting persisted. And we have essentially the same thing as we did with the event dispatcher.

Conclusion

In this article we have taken a look at how the Symfony Event Dispatcher component works in Drupal 8. We’ve learned how flexible it makes our application when it comes to allowing others to extend functionality. Additionally, we’ve seen how the invoked hooks work in the new version of Drupal. Not much has changed since Drupal 7 in this respect apart from the frequency with which they are used. Many hooks have been replaced by plugins and annotations and the Event Dispatcher component has also taken on a big chunk of what was in D7 a hook responsibility.

Although the Event Dispatcher approach is more verbose, it is the recommended way to go forward. Where possible, we no longer use the old procedural approach characteristic to hooks but rather object oriented, decoupled and testable solutions. And Symfony helps greatly with that.

Oct 06 2014
Oct 06

One Drupalcon session of particular interest to many in the community, since the first “episode”, has been the “Q&A with Dries”, a core-conversation-track session in which Dries is joined by a panel of his initiative leads and others in the “inner circle” of Drupal 8 core development. Since I’d wished, in the past, that sessions like these had a video recording to show who was talking, I brought my DSLR and a shotgun microphone this time, thinking I’d contribute the resulting video. I don’t think the video I shot was technically perfect enough to share; perhaps I could fix that, but I also realized that one panel member prefers to limit her exposure on the Web—and respect that, of course; since it’s much easier to blur or block out a face in a few images than in a video, and since you can read this summary in much less time than the hour+ -length session, I decided to provide stills from the video, along with a summary of the questions and answers, which ranged from the whimsical (a bet on how long it would be till Drupal 8 would be released as “stable”), to various business and architecture questions, and other concerns.

Q and A with Dries and panelists, Drupalcon Amsterdam

(You’ll find a more serious answer to that question if you read on...). Of course, Dries began by asking each of his panelists to introduce themselves. Those present were:

intro_gabor.jpgGábor Hojtsy, who works for Acquia and introduced himself, first, as the Drupal 6 maintainer; he also leads the Multilingual initiative for Drupal 8.

Nathaniel CatchpoleNathaniel Catchpole (catch), a major core maintainer with special focus on optimizing performance.

intro_alexpott.jpgAlex Pott, who works for ChapterThree, and supports Drupal as a core maintainer, also contributes actively in the configuration management initiative for Drupal 8.

yched introduces himselfYves Chedemois (yched), a freelancer and volunteer contributor to Drupal core, especially active as the maintainer of the Drupal 8 Field API (he formerly maintained CCK).

Wim Leers, core maintainerWim Leers (of Acquia, who works on the Spark initiative and Drupal 8 performance

Jess (xjm), who was the major heavy lifter for getting Views into Drupal 8 core, alongside her very active community mentoring role, now is most active with release planning and other steps toward getting Drupal 8 to the community.

Dries jokes and introduces himself as 'Drice'

Dries made everyone laugh, then, by introducing himself… and pronouncing his name as if it rhymed with “rice”. He followed by submitting the first questions to the panelists; these initial questions were selected from those emailed to him before the day of the session. Everyone had something to say for the first question.

Q: Are there any lessons learned, so far, from the Drupal 8 release cycle?

Alex Pott pointed out that changing core is taking longer and longer as the complexity increases and the needs of the greater Drupal community become more varied. “It’s no longer a matter of developers having a good idea and putting a patch on Drupal.org”, he said. You have to get everything reviewed and tested and re-tested, usually through many iterations, before a patch finally makes it into core.

Yves Chedemois (yched) added that it really helped having a bigger team of people assisting in the Field API initiative, compared to how things have sometimes been in the past, before the initiatives, with only one or two people working on a particular sub-system; so now he might have five or six developers actively supporting him and who are all able to review each others work, and take over from one another if anyone is ill or leaves the team. He pointed out that, of course, finding five or six people who can keep active for the full 2-3 years that has been this development cycle has been one challenge; it’s just not realistic to expect.

Gábor weighed in with the fact that the whole extra communication with the community was something that hadn’t been so present before and has helped to find people identify their strengths and find ways to contribute to the development process. Extra communications on Drupal.org, the core conversations like this Q&A session, and the initiatives, themselves, helped to build a better level of involvement and ability to contribute.

Dries also added that people asked whether the initiatives, themselves, were a success, and wanted to say that he, indeed, found them very useful for the development cycle. It helped communicate a sort of roadmap for Drupal with the key areas that needed work. Having clearly communicated, specific goals, and teams working with specific areas of interest, in turn helped gather more people to help. He pointed out that the initiatives which were most successful in gathering a team to rally to their cause tended to be the ones with leaders with the best ability to communicate their goals; and of course they also had to have great technical skills and be skilled project managers. Dries added that, if he were to do it again, he would try to get a small team together for each initiative, from the start, with individuals able to bring all important strengths to work for each initiative. It’s a lot to ask from one person.

Q: How do you best prepare for Drupal 8?

Nathaniel Catchpole (catch), suggested that if you are a site-builder, experiment with building up a Drupal 8 version of a site you want to migrate to Drupal 8, or just begin building up a site; just remember that we are just at the first beta, so things might be changing. But if you just practice building up your site structure and learn what you can do, that can be very helpful as a first step to being comfortable with Drupal 8.

Wim Leers added that it’s a good time for the community to get the input from experienced site builders who have familiarity with how things work in Drupal 7 and might find some areas where performance or user experience have been affected in a negative manner; there might still be time to fix remaining issues identified now.

Jess recommended that users who need to migrate from Drupal 6, which is scheduled for “end of life” about six months after the release of a stable Drupal 8.0.0, practice building up the functionality they need in Drupal 8, determining any areas where core functionality doesn’t fill their requirements. A lot of functionality which was formerly only in contrib is now in core, but you can identify what contrib modules you still need to see ported. Keep your Drupal 6 site running, but you can locally test and practice the migration path from Drupal 6 to Drupal 8. Currently this path lacks a user interface and has some other rough areas, but there is documentation. Then you can follow and support the development of contrib modules that are blockers for your ideal upgrade.

Alex Pott added that if you are a PHP developer, it’s a good time to be learning about all the new object-oriented stuff in core; getting your head around that. He recommended looking at PHP: The Right Way for some good tips. Themers should work on learning Twig and a new base theme, Classy, just committed to Drupal 8. But beware, the others added: the theme layer will not be frozen until closer to the final release date, so there are still some things that will change. Also, there is now a full-featured Entity API in core, so when modeling your site, think in terms of entities and think about what is really content or not.

Gábor reminded us that even if you aren’t ready to dive into Drupal 8, there are a lot of good talks, blog posts, and development surrounding bringing a lot of “Drupal 8 improvements” into Drupal 7 sites, so you can learn your way around PHPUnit, Composer, etc, as a first step to getting comfortable with Drupal 8.

Dries then opened the floor to additional questions from the audience. The first participant actually asked two questions, one more serious than the other.

Q: If you had to bet on the release date for Drupal 8, what date would that be?

That guy who asked three questions...This question got a good laugh and perhaps more discussion time than was necessary. After skipping it to take his serious question, this one actually did get some answer time; Jess made some cogent points: that it’s not a good idea to base business decisions on any predictions around the release date of Drupal 8, but that the community is betting on it being soon and successful. She suggested that any really large projects which will take years to develop are good candidates for looking at the components of Drupal 8 as appropriate building blocks and starting work. His second question was one that, perhaps other developers who haven’t yet worked (much) with Drupal 8 code, could relate to.

Q: In the past, someone who doesn’t do a lot of development could still make a simple tweak to simple module. Now there is so much code for the new Symfony-based modules. Isn’t all this code scary?

catch pointed out that once you are familiar with it, there are still lots of places you can easily make the same kind of tweaks with Views in core, and with plugins and the configuration management. yched added that most of the hooks available in Drupal 7 are still available. Gábor said that he could remember a time, not so long ago, when he’d also been daunted by the complexity and differences between the way things are done in Drupal 8 versus how they were done in Drupal 7, but after starting to work with it, you will learn the new patterns and it starts to make sense and actually be easier, in many ways. Dries added that it’s common to be daunted by the “more-lines-of-code”, but that the object orientation actually reduces the complexity and makes it easier to extend and understand, once you are familiar with the design patterns. He also pointed out that in Drupal 7 you had to know all the hooks and that now, it’s more declarative and you can work with what you want to happen, based on events. So there is less you need to learn, and less “magic”.

Wim reminded us that Drupal 8 introduces greater strictness, which translates to an increase in verbosity, but also makes it easier to find and avoid problems.

Q: How does Drupal 8 architecture matter to clients? Why should they care about developing a site in Drupal 8?

Chris Amato, aka knectar on drupal.orgChris Amato (knectar) asked this question, to which Dries began by pointing out that there is a lot more support “out-of-the-box” for things like mobile content, with responsive designs and services deeply integrated. yched added that every entity type is now natively translatable and versionable and that every field can be manipulated with the same familiar tools. Gábor added that there are lot more Views and things that can be individually tweaked to a clients needs. Even admin pages are Views-based and the modules you use will also incorporate this flexibility, so there should be less need for hacks to work around what a client needs.

The next question had to do with decoupling in Drupal 8 and so-called “headless Drupal”

Q: (paraphrased) How does “headless Drupal” and decoupling fit in and is this something we will be seeing more of in Drupal 9?

The guy who asked about headless Drupal in Drupal 9Dries said that it was really too early to know what the focus of Drupal 9 would be, but that it would likely involve greater decoupling, yes. Others pointed out that it’s already possible to do a lot with headless Drupal and that we can look for a big growth in that direction coming from contrib and possibly making its way into core before Drupal 9.

The next question brought us to the issue of documentation.

Q: Will there be some books for Drupal 8 and better documentation?

That guy who asked about documentation...Gábor started by pointing out that there is already a Drupal 8 API section, a lot of which is pretty well fleshed-out. There are still places for people to get involved and help update since there have been so many changes since the initial pages were written. And Jennifer Hodgdon is already working on a book for Drupal 8 development. Dries pointed out that there are now about 50 or so books on Drupal 7, and that things are still changing enough it’s still too early for publication of Drupal 8 books, but that we can expect a variety of books on Drupal 8 soon after its release. The API documentation and other Drupal 8 usage documentation is in various stages of completion. xjm pointed out that we need help with the documentation on drupal.org and that this is a great way to get involved.

Q: “What is being done or can be done to help bring funding to Drupal development?” (heavily paraphrased)

Rudi van Es of the local Amsterdam Drupal community

Rudi van Es, an Amsterdam-based member of the local Drupal shop, limongroen, came with this question.

Dries indicated that the Drupal Association can sometimes help find parties who would also benefit from certain development to help find funding for some projects, but that this is part of what Large Scale Drupal is working to accomplish and that maybe we also need a “Small Scale Drupal” to work more directly with individual developers. Some of the funding that has already come out of Large Scale Drupal went into improving workflows for media and publishing companies on Drupal; this effort has been added to the Workbench project. Dries also reminded us of his keynote, where he discussed better incentivizing contribution. And some organizations might be more willing or able to donate than actual time and expertise to Drupal development. Dries acknowledged that there are limits to the number of companies who are actively funding Drupal projects and initiatives and this is one of the challenges facing the community. While Wikipedia has been able to successfully crowdfund, they have a unique advantage in being able to directly access the end users; Drupal end-users are largely unaware of Drupal.

Q: Is it possible for us to reach a point where we can remove the trouble of upgrading and Drupal is just Drupal, regardless of version number?

Matt Smith, aka smithworx on Drupal.orgThat question came from Matt Smith of Lingotek, who asked a question I have asked before; a tough question. catch started by discussing what they have planned for Drupal releases now, which is already a huge improvement, that Drupal 8.1.0 and 8.2.0 can bring new functional improvements without breaking the API and that by growing slowly, they can minimize the API breakage needed when when it finally is necessary, to re-think a way of doing something and that would be the point we move to 9.x development. We might not be able to avoid breaking the API, because avoiding this can put us in a place the we have to deal with stagnation, but we will make our best efforts to minimize this going forward and it may be that in the beginning of Drupal 9, modules that have worked with each progressive minor version will, mostly not be broken by the initial changes in Drupal 9. As the architecture becomes closer to ideal, we should be able to greatly improve this, as we move forward. xjm added that the release cycle they have adopted now is like Ubuntu and there will be long-term support for some releases.

The final question taken was about tools. In short, the question was…

Q: What development tools are you (core committers) using to manage your work?

That guy again... asking the third questionThis question came, again, from the same fellow (sorry, I didn’t quite get your name), who asked “stable release date”, and the “Isn’t the big, new code complicated and scary?” questions. As the code-base becomes more and more complex, people who used to simply work with a text editor are finding it harder to manage and more and more developers are using IDEs, in particular PHPStorm, which this guy felt seems to be so prevalent now as to be almost a “soft requirement” for Drupal development.

Here, Dries suggested each of the panelists provide a quick answer about their preferred editors of choice and then wrap up the session: xjm started by saying she still mostly uses Emacs, but has started “tasting the forbidden fruit of an IDE in the form of PHPStorm” and said that without 16 years of using Emacs, it wouldn’t be a tough decision. It does make your development life a bit more sane. Gábor said that he has adopted PHPStorm. catch said that he’s still using Vim and holding out as long as he can, but will probably give in at some point and start using PHPStorm. There was brief discussion then, about fear that if everyone adopts a commercial product like PHPStorm, that this could lead to JetBrains taking advantage of us with monopolistic behavior. (Personally, I'm not worried and have respect for the offer they continue to honor: free licenses for open-source contributors.) Moving back to the panel, Alex Pott confessed that he uses PHPStorm. yched also uses PHPStorm and added that it really just makes navigating a large object-oriented codebase so much simpler; navigating between the classes, implementations, overrides, and so on. Wim Leers said that he continued to use text editors until a few months ago and has now also started using PHPStorm. Dries joked that he uses email, then confessed that he doesn’t get to code that much these days, so shouldn’t be taken as a reference, but still uses vi when he needs to make some quick changes.

Final thoughts…

It may be late in the game, but it’s a good time to help with the final work to get all the biggest bugs resolved so that Drupal 8 can be considered stable. There are lots of way to help, from identifying issues (beta testing or areas where documentation is lacking, etc), to simply verifying that bugfixes do what they are supposed to do. And there are a lot of nice tools, now, for helping review tickets. If tickets can be reviewed right away, it is more likely they just get finished before they drag on for months, require “re-rolls”, and all those hassles, and many such tickets are not difficult to review. I’m glad I made it to the Drupalcon rather than just watching/listening when I had the time.

And I should probably say that it’s been far too long since I’ve written a Drupal-related blog post here. I’m not going to make excuses: the truth is that I’ve been pretty much inundated with OtherStuff™, including some work on a complex, semi-mature project which only involves Drupal and so stopped having time to contribute, look at much actual Drupal code, or spend much time learning about all the “new things” going on. So I didn’t feel qualified to write about what was going on in the Drupal world. But I came to Cocomore for the Drupal, so I’ll work on reaching a better balance and hope to find time between all the OtherStuff™ to see you again, soon. The sprint Friday and weekend got my Drupal-thirst going again; Randi and I are already looking at a vacation rental for the full week in Barcelona next year (woohoo!), so you can count on it at least not being too long.

Aug 20 2014
Aug 20

We are excited to announce today the amazing keynote speakers that we have lined up for our php[world] conference this November. We’ve worked hard to find the best speakers and talks that cover the breadth of the PHP experience. We want php[world] to be a conference that pulls together all the different fragmented communities of PHP into one place to share ideas, and our keynotes reflect that mission.

We will have Luke Stokes, Co-Founder and CTO of FoxyCart, speaking on his experience of forming his own company. Angela Byron, a core committer to the Drupal Project and Director of Community Development at Acquia, is going to talk to us about the efforts Drupal has been making to break out of its own community and embrace libraries from other projects. Andrew Nacin, a WordPress Lead Developer, is going to share how WordPress built their automatic security updates and convinced their community of its benefits. Also, Jeffrey “Jam” McQuire, Open Source Evangelist at Acquia, will present how the Open Source Software revolution, with PHP leading the way, is making for better business, better government, and, he hopes, a better world!

Finally we are going to wrap up the conference with “The Greatest Panel on Earth.” We will have key people representing seven of the biggest PHP frameworks and applications: WordPress, Drupal, Magento, Joomla!, Symfony, Laravel, and Zend Framework all together in one place to answer all your most difficult questions!

Read on for full descriptions of all the keynotes, or you can visit our php[world] schedule or speaker list online. Register soon and book your hotel before our block sells out! We look forward to seeing you in D.C. this fall!

Turning Your Code Into a Company: The Parts They Don’t Tell You.

Somewhere around 2005 and 2006 my friend and I started tinkering around with building a better shopping cart experience because all the others sucked. Since 2007, we’ve processed over half a billion dollars worth of transactions and enabled thousands of online stores. It was really, really hard. This talk will tell the story of taking some code and persevering it into a company called FoxyCart. If you’ve ever wanted the liberty of being your own boss, hopefully you’ll find yourself in this story and determine if you have what it takes to succeed.

BIO: Luke Stokes is the Co-founder and CTO of FoxyCart.com. Enjoying Nashville, TN with his beautiful wife and three children, he’s passionate about living life on purpose. He’s pragmatic enough to get things done but idealistic enough to still believe we can change the world and make it better. He built his first websites in 1996 (yes, AOL and Geocities) and has been hacking at computers ever since. Always opinionated, he loves a good debate on liberty, Bitcoin, programming or anything interesting. He’s also a generally outgoing guy (for a programmer) and loves connecting with people.

Drupal 8: A Story of Growing Up and Getting Off the Island

The Drupal project has traditionally held a strong internal value for doing things “The Drupal Way.” As a result, Drupal developers have historically needed to build up reams and reams of tricks and workarounds that were specific to Drupal itself, and Drupal was inaccessible to people with a more traditional programming background.

Starting in Drupal 8, however, we’ve effectively done a ground-up rewrite of the underlying code and in the process made major inroads to getting more inline with the rest of the PHP world. Procedural code is out, OO code is in. “Creative” hacks have been replaced with FIG standards. “Not invented here” is now “Proudly found elsewhere.”

This story will talk about the journey that Drupal 8 and the Drupal core development team has taken during this transition over the past 3+ years, including some of the pros and cons of this approach and how we dealt (and are dealing) with some of the community management challenges that resulted.

BIO: Angela Byron is Drupal core committer and Director of Community Development at Acquia. She got her start as a Google Summer of Code student in 2005 and since then has completely immersed herself in the Drupal community. Her work includes reviewing and committing Drupal core patches, supporting community contributors, coordinating with the Drupal.org infrastructure team, and evangelizing Drupal. Angela is the lead author of O’Reilly’s first Drupal book, entitled Using Drupal. She is on the Board of Directors for the Drupal Association. Angie is known as “webchick” on drupal.org.

Idealism as code: From philosophy to empowerment

As part of the LAMP stack, PHP is a dominant web technology and it is getting more powerful all the time: Convergence through things like Composer and the PSR standards is bringing once disparate communities together. Multiple “meta projects” like Drupal are adopting code from around the PHP and FOSS spheres. Contribution to one has become contribution to whole ecosystems.

Many of us are idealists. Powering 80% of the web, we have the chance – and perhaps the responsibility – to make a difference through PHP. Paraphrasing Angie “Webchick” Byron, Drupal core committer, “We make really abstract complicated programming concepts accessible to non-developers, available to them by clicking a few buttons, without having to understand all the code that comes underneath it. What I get really excited about is the idea that we create really easily accessible things to help those people who are on the front lines trying to make the world a better place. We can build technology to enable that.”

I will talk about how the thinking of RSM and other pioneers became code and how that code is empowering people and organisations. I want to draw a few lines from the very definition of free and open source software, through its practical application and native advantages, to how it helps people do better business, better government … and I’m hoping … make a better world.

BIO: Jeffrey A. “jam” McGuire, Open Source Evangelist at Acquia, is involved at the intersection of open source software, business, and culture. A memorable and charismatic communicator, he receives enthusiastic responses from audiences at events around the world, where he talks about open source technology and community, digital disruption, Drupal and more. This helps satisfy his inner diva, which he also feeds with performances as a storyteller and musician.

Trust, Community, and Automatic Updates

In October 2013, WordPress shipped what is perhaps its most polarizing feature ever — automatic updates in the background of self-hosted web software, on by default and no easy way to turn it off. In most open source communities, this would be cause for open revolt. Learn how through trust, communication, and a steadfast commitment to its philosophies, the WordPress core team convinced a skeptical community to go along, even if it meant users giving up some control.

BIO: Andrew Nacin is a lead developer of WordPress, wrangling contributions, spearheading initiatives, advising new development, and squashing bugs. He feels strongly about the core philosophies of WordPress, among them “decisions, not options” — software should be opinionated in lieu of burdening the user with too many options. He works for WordPress founder Matt Mullenweg at Audrey Capital, where he is primarily tasked with working on WordPress core and keeping the lights on at WordPress.org. He resides in downtown Washington, D.C., with his wife.

The Greatest Panel on Earth

Join us for our closing keynote! Have you ever wanted to ask the various framework and application developers questions? Want to see each of their different points of view (and maybe get them to debate a few hot topics)? This is your chance. We are gathering a panel of core developers from WordPress, Drupal, Magento, Joomla!, Symfony, Laravel, and Zend Framework. They’ll be ready to have a discussion and answer your questions.

About the author—Eli has been a PHP coder since the day PHP 4 was released. He's worked for numerous companies in the past, such as Digg.com, Zend Technologies, TripAdvisor, mojoLive, and Goodsie. Though found himself in love with the PHP community so deeply that he ended up here at php[architect], and loves what he does. Conferences, magazine, books, training - Teaching people the love for the language that he himself has.

Jun 18 2014
Jun 18

How to Build a Drupal 8 Module

In the previous article on Drupal 8 module development, we’ve looked at creating block types and forms. We’ve seen that blocks are now reusable and how everything we need to do for defining block types happens in one single class. Similarly, form generation functions are also grouped under one class with specific methods performing tasks similar to what we are used to in Drupal 7.

In this tutorial, I will continue where we left off. I will illustrate how we can turn our DemoForm into a form used to store a value through the Drupal 8 configuration system. Following that, we will talk a bit about the service container and dependency injection by way of illustration.

Don’t forget that you can check out this repository if you want to get all the code we write in this tutorial series.

When we first defined our DemoForm, we extended the FormBase class which is the simplest implementation of the FormInterface. However, Drupal 8 also comes with a ConfigFormBase that provides some additional functionality which makes it very easy to interact with the configuration system.

What we will do now is transform DemoForm into one which will be used to store the email address the user enters. The first thing we should do is replace the extended class with ConfigFormBase (and of course use it):

use Drupal\Core\Form\ConfigFormBase;

class DemoForm extends ConfigFormBase {

Before we move on to changing other things in the form, let’s understand a bit how simple configuration works in Drupal 8. I say simple because there are also configuration entities that are more complex and that we will not cover today. As it stands now, configuration provided by modules (core or contrib) is stored in YAML files. On enabling a module, this data gets imported into the database (for better performance while working with it). Through the UI we can change this configuration which is then easily exportable to YAML files for deployment across different sites.

A module can provide default configuration in a YAML file located in the config/install folder in the module root directory. The convention for naming this file is to prefix it with the name of the module. So let’s create one called demo.settings.yml. Inside this file, let’s paste the following:

demo:
  email_address: [email protected]

This is a nested structure (like an associative array in PHP). Under the key demo, we have another key|value pair. And usually to access these nested values we use a dot(.). In our case demo.email_address.

Once we have this file in place, an important thing you need to remember is that this file gets imported only when the module is installed. So go ahead and reinstall it. And now we can turn back to our form and go through the methods that need adapting one by one.

This is how the buildForm() method should look like now:

public function buildForm(array $form, array &$form_state) {
  
  $form = parent::buildForm($form, $form_state);
  
  $config = $this->config('demo.settings');
  
  $form['email'] = array(
    '#type' => 'email',
    '#title' => $this->t('Your .com email address.'),
    '#default_value' => $config->get('demo.email_address')
  );
  
  return $form;
}

First of all, as opposed to FormBase, the ConfigFormBase class implements this method as well in order to add elements to the form array (a submit button). So we can use what the parent did before adding our own elements.

Now for the configuration part. Drupal 8 provides a Config object that we can use to interact with the configuration. Some classes already have it available through dependency injection. ConfigFormBase is one such class.

As you can see, we are using the config() method of the parent class to retrieve a Config object populated with our demo.settings simple configuration. Then, for the #default_value of the email form element, we use the get() method of the Config object to retrieve the value of the email address.

Next, we only need to change the submit handler because the validateForm() method can stay the same for now:

public function submitForm(array &$form, array &$form_state) {
  
  $config = $this->config('demo.settings');
  $config->set('demo.email_address', $form_state['values']['email']);
  $config->save();
  
  return parent::submitForm($form, $form_state);
}

In this method we first retrieve the Config object for our configuration (like we did before). Then, we use its set() method to change the value of the email_address to the value the user submitted. Then we use the save() method to save the configuration. Lastly, we extend the parent submit handler because it does contain some functionality (in this case it sets a Drupal message to the screen).

And that’s pretty much it. You can clear the cache and try it out. By submitting a new email address, you are storing it in the configuration. The module demo.settings.yml file won’t change of course, but you can go and export the demo.settings configuration and import it into another site.

The service container and dependency injection

The next thing we are going to look at is the service container. The idea behind services is to split functionality into reusable components. Therefore a service is a PHP class that performs some global operations and that is registered with the service container in order to be accessed.

Dependency injection is the way through which we pass objects to other objects in order to ensure decoupling. Each service needs to deal with one thing and if it needs another service, the latter can be injected into the former. But we’ll see how in a minute.

Going forward, we will create a very simple service and register it with the container. It will only have one real method that returns a simple value. Then, we will inject that service as a dependency to our DemoController and make use of the value provided by the service.

In order to register a service, we need to create a demo.services.yml file located in the root of our module, with the following contents:

services:
    demo.demo_service:
        class: Drupal\demo\DemoService

The file naming convention is module_name.services.yml.

The first line creates an array of services. The second line defines the first service (called demo_service, prefixed by the module name). The third line specifies the class that will be instantiated for this service. It follows to create the DemoService.php class file in the src/ folder of our module. This is what my service does (nothing really, it’s just to illustrate how to use it):

<?php

/**
 * @file
 * Contains Drupal\demo\DemoService.
 */

namespace Drupal\demo;

class DemoService {
  
  protected $demo_value;
  
  public function __construct() {
    $this->demo_value = 'Upchuk';
  }
  
  public function getDemoValue() {
    return $this->demo_value;
  }
  
}

No need to explain anything here as it’s very basic. Next, let’s turn to our DemoController and use this service. There are two ways we can do this: accessing the container globally through the \Drupal class or use dependency injection to pass an object of this class to our controller. Best practice says we should do it the second way, so that’s what we’ll do. But sometimes you will need to access a service globally. For that, you can do something like this:

$service = \Drupal::service('demo.demo_service');

And now $service is an object of the class DemoService we just created. But let’s see how to inject our service in the DemoController class as a dependency. I will explain first what needs to be done, then you’ll see the entire controller with all the changes made to it.

First, we need access to the service container. With controllers, this is really easy. We can extend the ControllerBase class which gives us that in addition to some other helpers. Alternatively, our Controller can implement the ContainerInjectionInterface that also gives us access to the container. But we’ll stick to ControllerBase so we’ll need to use that class.

Next, we need to also use the Symfony 2 ContainerInterface as a requirement of the create() method that instantiates another object of our controller class and passes to it the services we want.

Finally, we’ll need a constructor to get the passed service objects (the ones that create() returns) and assign them to properties for later use. The order in which the objects are returned by the create() method needs to be reflected in the order they are passed to the constructor.

So let’s see our revised DemoController:

<?php

/**
 * @file
 * Contains \Drupal\demo\Controller\DemoController.
 */

namespace Drupal\demo\Controller;

use Drupal\Core\Controller\ControllerBase;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * DemoController.
 */
class DemoController extends ControllerBase {
  
  protected $demoService;
  
  /**
   * Class constructor.
   */
  public function __construct($demoService) {
    $this->demoService = $demoService;
  }
  
  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('demo.demo_service')
    );
  }
  
  /**
   * Generates an example page.
   */
  public function demo() {
    return array(
      '#markup' => t('Hello @value!', array('@value' => $this->demoService->getDemoValue())),
    );
  }
}

As you can see, all the steps are there. The create() method creates a new instance of our controller class passing to it our service retrieved from the container. And in the end, an instance of the DemoService class gets stored in the $demoService property, and we can use it to call its getDemoValue() method. And this value is then used in the Hello message. Clear your cache and give it a try. Go to the demo/ path and you should see Hello Upchuk! printed on the page.

I’m sure you can see the power of the service container as we can now write decoupled functionality and pass it where it’s needed. I did not show you how, but you can also declare dependencies when you register services. This means that when Drupal instantiates a service object, it will do so for all its dependencies as well, and pass them to its constructor. You can read more about how to do that on this documentation page.

Conclusion

In this article we’ve looked at a lot of cool stuff. We’ve seen how the configuration system manages simple configuration and what we have available form-wise for this. I do encourage you to explore how the ConfigFormBase is implemented and what you have available if you extend it. Additionally, you should play around in the UI with importing/exporting configuration between sites. This will be a great improvement for the deployment process from now on.

Then, we looked at services, what they are and how they work. A great way of maintaining reusable and decoupled pieces of functionality accessible from anywhere. And I do hope the concept of dependency injection is no longer so scary (if it was for you). It is basically the equivalent of passing parameters to procedural functions, but done using constructor methods (or setters), under the hood, by Symfony and its great service container.

Jun 16 2014
Jun 16

How to Build a Drupal 8 Module

In the first installment of this article series on Drupal 8 module development we started with the basics. We’ve seen what files were needed to let Drupal know about our module, how the routing process works and how to create menu links programatically as configuration.

In this tutorial we are going to go a bit further with our sandbox module found in this repository and look at two new important pieces of functionality: blocks and forms. To this end, we will create a custom block that returns some configurable text. After that, we will create a simple form used to print out user submitted values to the screen.

Drupal 8 blocks

A cool new change to the block API in D8 has been a switch to making blocks more prominent, by making them plugins (a brand new concept). What this means is that they are reusable pieces of functionality (under the hood) as you can now create a block in the UI and reuse it across the site – you are no longer limited to using a block only one time.

Let’s go ahead and create a simple block type that prints to the screen Hello World! by default. All we need to work with is one class file located in the src/Plugin/Block folder of our module’s root directory. Let’s call our new block type DemoBlock, and naturally it needs to reside in a file called DemoBlock.php. Inside this file, we can start with the following:

<?php

namespace Drupal\demo\Plugin\Block;

use Drupal\block\BlockBase;
use Drupal\Core\Session\AccountInterface;

/**
 * Provides a 'Demo' block.
 *
 * @Block(
 *   id = "demo_block",
 *   admin_label = @Translation("Demo block"),
 * )
 */

class DemoBlock extends BlockBase {
  
  /**
   * {@inheritdoc}
   */
  public function build() {    
    return array(
      '#markup' => $this->t('Hello World!'),
    );
  }
  
  /**
   * {@inheritdoc}
   */
  public function access(AccountInterface $account) {
    return $account->hasPermission('access content');
  }  
  
}

Like with all other class files we start by namespacing our class. Then we use the BlockBase class so that we can extend it, as well as the AccountInterface class so that we can get access to the currently logged in user. Then follows something you definitely have not seen in Drupal 7: annotations.

Annotations are a PHP discovery tool located in the comment block of the same file as the class definition. Using these annotations we let Drupal know that we want to register a new block type (@Block) with the id of demo_block and the admin_label of Demo block (passed through the translation system).

Next, we extend the BlockBase class into our own DemoBlock, inside of which we implement two methods (the most common ones you’ll implement). The build() method is the most important as it returns a renderable array the block will print out. The access() method controls access rights for viewing this block. The parameter passed to it is an instance of the AccountInterface class which will be in this case the current user.

Another interesting thing to note is that we are no longer using the t() function globally for translation but we reference the t() method implemented in the class parent.

And that’s it, you can clear the caches and go to the Block layout configuration page. The cool thing is that you have the block types on the right (that you can filter through) and you can place one or more blocks of those types to various regions on the site.

Drupal 8 block configuration

Now that we’ve seen how to create a new block type to use from the UI, let’s tap further into the API and add a configuration form for it. We will make it so that you can edit the block, specify a name in a textfield and then the block will say hello to that name rather than the world.

First, we’ll need to define the form that contains our textfield. So inside our DemoBlock class we can add a new method called blockForm():

/**
 * {@inheritdoc}
 */
public function blockForm($form, &$form_state) {
  
  $form = parent::blockForm($form, $form_state);
  
  $config = $this->getConfiguration();

  $form['demo_block_settings'] = array(
    '#type' => 'textfield',
    '#title' => $this->t('Who'),
    '#description' => $this->t('Who do you want to say hello to?'),
    '#default_value' => isset($config['demo_block_settings']) ? $config['demo_block_settings'] : '',
  );
  
  return $form;
}

This form API implementation should look very familiar from Drupal 7. There are, however, some new things going on here. First, we retrieve the $form array from the parent class (so we are building on the existing form by adding our own field). Standard OOP stuff. Then, we retrieve and store the configuration for this block. The BlockBase class defines the getConfiguration() method that does this for us. And we place the demo_block_settings value as the #default_value in case it has been set already.

Next, it’s time for the submit handler of this form that will process the value of our field and store it in the block’s configuration:

/**
* {@inheritdoc}
*/
public function blockSubmit($form, &$form_state) {
 
 $this->setConfigurationValue('demo_block_settings', $form_state['values']['demo_block_settings']);
 
} 

This method also goes inside the DemoBlock class and all it does is save the value of the demo_block_settings field as a new item in the block’s configuration (keyed by the same name for consistency).

Lastly, we need to adapt our build() method to include the name to say hello to:

 /**
 * {@inheritdoc}
 */
public function build() {
  
  $config = $this->getConfiguration();
  
  if (isset($config['demo_block_settings']) && !empty($config['demo_block_settings'])) {
    $name = $config['demo_block_settings'];
  }
  else {
    $name = $this->t('to no one');
  }
  
  return array(
    '#markup' => $this->t('Hello @name!', array('@name' => $name)),
  );  
}

By now, this should look fairly easy. We are retrieving the block’s configuration and if the value of our field is set, we use it for the printed statement. If not, use use a generic one. You can clear the cache and test it out by editing the block you assigned to a region and add a name to say hello to. One thing to keep in mind is that you are still responsible for sanitizing user input upon printing to the screen. I have not included these steps for brevity.

Drupal 8 forms

The last thing we are going to explore in this tutorial is how to create a simple form. Due to space limitations, I will not cover the configuration management aspect of it (storing configuration values submitted through forms). Rather, I will illustrate a simple form definition, the values submitted being simply printed on the screen to show that it works.

In Drupal 8, form definition functions are all grouped together inside a class. So let’s define our simple DemoForm class inside src/Form/DemoForm.php:

<?php

/**
 * @file
 * Contains \Drupal\demo\Form\DemoForm.
 */

namespace Drupal\demo\Form;

use Drupal\Core\Form\FormBase;

class DemoForm extends FormBase {
  
  /**
   * {@inheritdoc}.
   */
  public function getFormId() {
    return 'demo_form';
  }
  
  /**
   * {@inheritdoc}.
   */
  public function buildForm(array $form, array &$form_state) {
    
    $form['email'] = array(
      '#type' => 'email',
      '#title' => $this->t('Your .com email address.')
    );
    $form['show'] = array(
      '#type' => 'submit',
      '#value' => $this->t('Submit'),
    );
    
    return $form;
  }
  
  /**
   * {@inheritdoc}
   */
  public function validateForm(array &$form, array &$form_state) {
    
    if (strpos($form_state['values']['email'], '.com') === FALSE ) {
      $this->setFormError('email', $form_state, $this->t('This is not a .com email address.'));
    } 
  }
  
  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, array &$form_state) {
    
    drupal_set_message($this->t('Your email address is @email', array('@email' => $form_state['values']['email'])));
  }
  
}

Apart from the OOP side of it, everything should look very familiar to Drupal 7. The Form API has remained pretty much unchanged (except for the addition of some new form elements and this class encapsulation). So what happens above?

First, we namespace the class and use the core FormBase class so we can extend it with our own DemoForm class. Then we implement 4 methods, 3 of which should look very familiar. The getFormId() method is new and mandatory, used simply to return the machine name of the form. The buildForm() method is again mandatory and it builds up the form. How? Just like you are used to from Drupal 7. The validateForm() method is optional and its purpose should also be quite clear from D7. And finally, the submitForm() method does the submission handling. Very logical and organised.

So what are we trying to achieve with this form? We have an email field (a new form element in Drupal 8) we want users to fill out. By default, Drupal checks whether the value input is in fact an email address. But in our validation function we make sure it is a .com email address and if not, we set a form error on the field. Lastly, the submit handler just prints a message on the page.

One last thing we need to do in order to use this form is provide a route for it. So edit the demo.routing.yml file and add the following:

demo.form:
  path: '/demo/form'
  defaults:
    _form: '\Drupal\demo\Form\DemoForm'
    _title: 'Demo Form'
  requirements:
    _permission: 'access content'

This should look familiar from the previous article in which we routed a simple page. The only big difference is that instead of _content under defaults, we use _form to specify that the target is a form class. And the value is therefore the class name we just created.

Clear the caches and navigate to demo/form to see the form and test it out.

If you are familiar with drupal_get_form() and are wondering how to load a form like we used to in Drupal 7, the answer is in the global Drupal class. Thus to retrieve a form, you can use its formBuilder() method and do something like this:

$form = \Drupal::formBuilder()->getForm('Drupal\demo\Form\DemoForm');

Then you can return $form which will be the renderable array of the form.

Conclusion

In this article we’ve continued our exploration of Drupal 8 module development with two new topics: blocks and forms. We’ve seen how to create our own block type we can use to create blocks in the UI. We’ve also learned how to add a custom configuration to it and store the values for later use. On the topic of forms, we’ve seen a simple implementation of the FormBase class that we used to print out to the screen the value submitted by the user.

In the next tutorial we will take a quick look at configuration forms. We will save the values submitted by the user using the Drupal 8 configuration system. Additionally, we will look at the service container and dependency injection and how those work in Drupal 8. See you then.

Oct 18 2012
Oct 18

Posted by admin

In preparation for my talk at Drupalcamp Spain 2012 about Symfony in Drupal 8 I made a list of some relevant issues and posts related to the topic. In pretty much chronological order.

TIMELINE

April 2010

September 2010

March 2011

April 2011

August 2011

June 2011

July 2011

August 2011

September 2011

October 2011

November 2011

December 2011

  • A PHP Christmas Miracle - 3 Frameworks, 1 app
  • Rethinking WSCCI
    • "However, after some additional research and discussion with Symfony2 folks I realized that what we were trying to do... Symfony2's component libraries already do."
    • "I propose that we cut to the chase and port Drupal to Symfony2's HttpKernel library, and accept the rather drastic changes that will result."

January 2012

February 2012

February 2012

March 2012

April 2012

May 2012

June 2012

July 2012

August 2012

October 2012

Mar 21 2012
Mar 21

The video and slides for my DrupalCon Denver 2012 session are already available.

The slides and video can be found at the official site. Kudos to the DrupalCon Denver organizers, who are in the midst of running a fantastic conference.

About Drupal Sun

Drupal Sun is an Evolving Web project. It allows you to:

  • Do full-text search on all the articles in Drupal Planet (thanks to Apache Solr)
  • Facet based on tags, author, or feed
  • Flip through articles quickly (with j/k or arrow keys) to find what you're interested in
  • View the entire article text inline, or in the context of the site where it was created

See the blog post at Evolving Web

Evolving Web