Drupal 8 simple page
A walk for Drupal 8 module development
@estoyausenteSamuel Solís
</spam>
Coupon code 10€ discount*
<spam>
#DrupalSummer2016
*if($totalAmount > 60€)
GO!
D7 Site building?
D7 modules?
PHP development?
Drupal 7
Drupal 8
This slides have examples
based on my experience
for more information please read
the API page
Index
1. Configuration manager
2. Routing
3. Forms
4. Services
5. Theming
Configuration manager
Impresiones
1. ¡Funciona!
2. ¡Funciona bien!
3. Overrides entre entornos -> Settings
4. ¿Menús?
5. Un poco caos
Configuration manager
Impresiones
1. ¡Funciona!
2. ¡Funciona bien!
3. Overrides entre entornos -> Settings
4. ¿Menús?
5. Un poco caos
Configuration manager
Impresiones
1. ¡Funciona!
2. ¡Funciona bien!
3. Overrides entre entornos -> Settings
4. ¿Menús?
5. Un poco caos
Configuration manager
Impresiones
1. ¡Funciona!
2. ¡Funciona bien!
3. Overrides entre entornos -> Settings
4. ¿Menús?
5. Un poco caos
Configuration manager
Impresiones
1. ¡Funciona!
2. ¡Funciona bien!
3. Overrides entre entornos -> Settings
4. ¿Menús?
5. Un poco caos
Configuration manager
Take a look
1. https://www.drupal.org/project/config_tools
2. https://www.drupal.org/project/config_update
3. https://www.drupal.org/project/config_sync
4. https://www.drupal.org/project/config_devel
5. https://www.drupal.org/project/features
Mi first module
Drupal
generate:module
Routing
example_dyb_landing_content:

path: '/landing-my-awsome-path'

defaults:

_controller: 'Drupalexample_dyb_landing
ControllerLandingContentController::pageContent'

requirements:

_access: 'TRUE'
example_dyb_landing/example_dyb_landing.routing.yml
Routing
example_dyb_landing_content:

path: '/landing-my-awsome-path'

defaults:

_controller: 'Drupalexample_dyb_landing
ControllerLandingContentController::pageContent'

requirements:

_access: 'TRUE'
example_dyb_landing/example_dyb_landing.routing.yml
Start with slash /
Controller
namespace Drupalexample_dyb_landingController;



use DrupalCoreControllerControllerBase;

use DrupalCoreUrl;



class LandingContentController extends
ControllerBase {

public function pageContent() {
$content = []; //Render array
return $content;

}

}
example_dyb_landing/src/Controllers/LandingContentController.php
Forms
namespace Drupalexample_dyb_landingForm;



use DrupalCoreFormFormBase;

use DrupalCoreFormFormStateInterface;



class ContactForm extends FormBase {



public function getFormId() {

return 'contact_form';

}
example_dyb_landing/src/Form/ContactForm.php
Forms
public function buildForm(array $form,
FormStateInterface $form_state) {
$form['mail'] = array(

'#type' => 'email',

'#title' => $this->t('Email'),

'#required' => TRUE,

'#attributes' => ['class' => ['formcontrol']],

);
return $form;

}
example_dyb_landing/src/Form/ContactForm.php
Forms
public function validateForm(array &$form,
FormStateInterface $form_state) {

$values = $form_state->getValues();



if(!Drupal::service('email.validator')-
>isValid($values['mail'])) {

$form_state->setErrorByName('mail', $this-
>t('The email address %mail is not valid.',
array('%mail' => $values['mail'])));

}
}
example_dyb_landing/src/Form/ContactForm.php
Forms


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



$values = $form_state->getValues();

$to = Drupal::config('system.site')->get('mail');

$language_interface = Drupal::languageManager()-
>getCurrentLanguage();



Drupal::service('plugin.manager.mail')-
>mail('example_dyb_landing', 'contact_message', $to,
$language_interface, $values, 'no-replyđ@mail.com');

drupal_set_message($this->t('Thank for contact us. Your
message has been sent correctly.'));

}
example_dyb_landing/src/Form/ContactForm.php
Forms
$output['bottom']['form'] = [

'#type' => 'container',

'#attributes' => ['class' => ['left']],

'form' => Drupal::formBuilder()-
>getForm('Drupalexample_dyb_landingForm
ContactForm'),

];
example_dyb_landing/src/Form/ContactForm.php
Forms
$output['bottom']['form'] = [

'#type' => 'container',

'#attributes' => ['class' => ['left']],

'form' => Drupal::formBuilder()-
>getForm('Drupalexample_dyb_landingForm
ContactForm'),

];
example_dyb_landing/src/Form/ContactForm.php
Services
*This is a spanish joke
*
Services
services:

rest_client.client:

class: Drupalrest_clientRestClient
example_dyb_landing/rest_client.services.yml
Services
namespace Drupalrest_client;



/**

* Class RestClient

* @package Drupalrest_client

*/

class RestClient{
protected $url;
public function __construct() {

$this->url = 'myserver.com';

}
example_dyb_landing/src/RestClient.php
Services
public function getSpecialities($country = 'ES') {



$cid = 'rest_client_getSpecialities_' . $country;

if ($cache = Drupal::cache()->get($cid)) {

return $cache->data;

}

//$output = getSomeStuff();
Drupal::cache()->set($cid, $output);

return $output;

}



return [];

}
example_dyb_landing/src/RestClient.php
Servicios
public function getSpecialities($country = 'ES') {



$cid = 'rest_client_getSpecialities_' . $country;

if ($cache = Drupal::cache()->get($cid)) {

return $cache->data;

}

//$output = getSomeStuff();
Drupal::cache()->set($cid, $output);

return $output;

}



return [];

}
example_dyb_landing/src/RestClient.php
dependencies:

- rest_client
example_dyb_landing/example_dyb_landing.info.yml
Dependency injection
namespace Drupalregister_formForm;

use Drupalrest_clientRestClient;
class RegisterForm extends FormBase{



protected $client;





public function __construct(RestClient $client) {

$this->client = $client;

}


public static function create(ContainerInterface $container) {

return new static(

$container->get('rest_client.client'),

);
}
example_dyb_landing/src/Form/RegisterForm.php
Dependency injection
Dependency injection


public function buildForm(array $form,
FormStateInterface $form_state) {

$form['speciality'] = [

'#type' => 'select',

'#options' => $this->client->getSpecialities(),

'#title' => $this->t('Speciality'),

'#required' => TRUE,

'#attributes' => ['class' => ['formcontrol']],

];
return $form;
}
example_dyb_landing/src/Form/RegisterForm.php
My first theme
Drupal generate:theme
Mi primer theme
name: public

type: theme

description: Public theme.

package: Other

core: 8.x

libraries:

- public/global-styling



base theme: classy



regions:

content: Content

header: Header

footer: Footer
public/public.info.yml
Add css/js
global-styling:

version: 1.x

css:

theme:

css/style.css: {}

js:

js/public.js: {}

dependencies:

- core/jquery

- core/drupal

- core/drupalSettings
public/public.libraries.yml
Preprocess
function public_preprocess_breadcrumb(&$variables){



//Add current page to breadcrumb.

$request = Drupal::request();

$route_match = Drupal::routeMatch();

$page_title = Drupal::service('title_resolver')-
>getTitle($request, $route_match->getRouteObject());

$variables['breadcrumb'][] = array(

'text' => $page_title,

);

}
public/public.theme
Twig
{% if breadcrumb %}

<nav class="breadcrumbs" role="navigation" aria-
labelledby="system-breadcrumb">

<h2 class="visually-hidden">{{ 'Breadcrumb'|t }}</h2>

<ol class="itemlistbread">

{% for item in breadcrumb %}

<li class="itembread">

{% if item.url %}

<a href="{{ item.url }}"
class="itembread__link">{{ item.text }}</a>

{% else %}

<span>{{ item.text }}</span>

{% endif %}

</li>

{% endfor %}

</ol>

</nav>

{% endif %}
public/templates/elements/breadcrumb.html.twig
Templates
<?php
db_query('DROP TABLE {users}’);
?>
Templates
<?php
db_query('DROP TABLE {users}’);
?>
Homework
• Caché
• Composer
• REST
• Migrate
• The change is so big…
Questions?
Thanks and enjoy this
DrupalSummer!
@estoyausenteSamuel Solís

Drupal8 simplepage v2