$30 off During Our Annual Pro Sale. View Details »

Drupal 8 Workshop: Introducción al Backend de Drupal

Drupal 8 Workshop: Introducción al Backend de Drupal

Introducción al Backend de Drupal es un taller impartido durante el Drupal Day Spain 2019 en Zaragoza, estas son las slides de la actividad.

Incluye aspectos como:
- Creación de módulos custom en Drupal
- Creación de formularios custom en Drupal
- Inyección de Dependencias para Servicios en Drupal
- Prefilling de valores en campos de formulario
- Comandos útiles para herramientas de consola en Drupal

David Rodríguez (davidjguru)

November 23, 2019
Tweet

More Decks by David Rodríguez (davidjguru)

Other Decks in Technology

Transcript

  1. INTRODUCCIÓN
    AL BACKEND
    DE DRUPAL
    (WORKSHOP)
    Zaragoza
    Drupal Day Spain 2019
    David Rodríguez
    @davidjguru
    1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12

    View Slide

  2. BIENVENIDA
    David Rodríguez Vicente
    (Drupal) Center Leader Specialist en Everis Sevilla
    Responsable técnico de Proyectos basados en Drupal
    Director técnico del equipo Drupal de Everis Center Sevilla
    Profile
    https://www.linkedin.com/in/davidjguru
    https://www.drupal.org/u/davidjguru
    Blogs
    https://medium.com/@davidjguru (esp)
    https://davidjguru.github.io (en)
    Repos
    https://gitlab.com/davidjguru
    https://github.com/davidjguru
    Contacto
    https://twitter.com/davidjguru
    [email protected]
    https://twitter.com/DrupalSevilla
    HELLO MY NAME IS.
    1, HOLA QUE TAL
    2

    View Slide

  3. Ver Drupal por dentro
    Introducción a tu nuevo backend favorito
    Progresivo, iterativo e incremental
    Asentemos conceptos básicos
    Observa las posibilidades
    Experiencia Inicial Motivadora
    Cogiendo cariño a Drupal
    PRESENTACIÓN
    2, dE QUÉ VA ESTO
    picture from Unsplash, user Konstantin Aal - @kostic86

    View Slide

  4. Practicaremos creando nuevos módulos Custom de Drupal.
    Expondremos los fundamentos del sistema de rutas y
    controladores de Drupal con la idea de construir accesos a
    nuestros formularios. Conoceremos los fundamentos de la
    creación de formularios con Drupal, crearemos varios tanto a
    mano como con su versión rápida usando Drupal Console.
    Dotaremos a los campos de formulario con valores ya cargados
    previamente, y para ese pre-filling de campo usaremos algunos
    servicios proporcionados por Drupal. Usaremos servicios web para
    realizar peticiones externas vía REST y cargar información en
    nuestros formularios. Realizaremos consultas a la base de datos y
    cargaremos valores dinámicamente en nuestro formulario.
    PRESENTACIÓN
    2, qUÉ VAMOS A HACER

    View Slide

  5. MÓDULOS CUSTOM EN DRUPAL RUTAS Y CONTROLADORES EN DRUPAL
    PERMISOS Y MENÚS EN DRUPAL FORMULARIOS EN DRUPAL
    COMANDOS ÚTILES EN DRUPAL INYECCIÓN DE DEPENDENCIAS EN DRUPAL
    PREFILLING DE VALORES EN CAMPOS
    BIENVENIDA PRESENTACIÓN
    LECTURAS RECOMENDADAS DESPEDIDA Y CIERRE
    PRESENTACIÓN
    CONSULTAS DINÁMICAS A LA BASE DE DATOS
    2, QUÉ VA A PASAR
    5

    View Slide

  6. MÓDULOS CUSTOM EN DRUPAL
    3, QUÉ ES UN MÓDULO
    6
    1- Elegir un nombre.
    2- Elegir un nombre corto,
    “machine_name”.
    3- Será usado en la creación de diversos
    ficheros internos.
    4- Servirá para identificar el módulo por
    parte del sistema Drupal.
    5- Debe empezar con una letra.
    6- Debe contener solo letras en minúscula y guiones
    bajos.
    7- Debe ser único y no puede coincidir con otro módulo,
    theme o profile.
    8- No debe contener palabras reservadas: lib, js, src, css,
    vendor, files, assets, images, templates, includes, Drupal.

    View Slide

  7. MÓDULOS CUSTOM EN DRUPAL
    3, CREAR UN MÓDULO
    /MODULES/CUSTOM/WORKSHOP_FORMS/
    WORKSHOP_FORMS.INFO.YML
    name: 'Workshop Forms'
    type: module
    description: 'My Custom Module for Forms.'
    core: 8.x
    package: 'Workshop'
    7

    View Slide

  8. RUTAS Y CONTROLADORES EN DRUPAL
    4, ESO DE ROUTING
    RUTA CONTROLADOR
    Esquema de definición de una ruta:
    Nombre de sistema (machine_name)
    Ruta física (path)
    Controladores: clase y método responsables
    Título
    Especificación de permisos
    Nos referimos en realidad a una clase que
    se hace responsable de gestionar el
    procesamiento de una ruta.
    Forma Class::method
    _controller:
    \Drupal\[module_name]\Controller\[ClassName]::[method]
    Forma Service:method
    _controller: ‘[name_service].controller:[method]’
    Forma ClassFormulario
    _form: ‘\Drupal\[module_name]\Form\[FormClassName]’
    Una ruta es (conceptualmente) el camino a
    seguir para alcanzar un destino a partir de
    un punto de partida.
    En Drupal se sigue el modelo de Symfony
    para gestionar rutas, basado en MVC, donde
    se definen rutas en un fichero descriptivo y
    se les asigna una clase responsable
    (Controlador, Formulario, Servicio).
    8

    View Slide

  9. RUTAS Y CONTROLADORES EN DRUPAL
    4, CREAR EL ROUTING
    /MODULES/CUSTOM/WORKSHOP_FORMS/
    WORKSHOP_FORMS.ROUTING.YML
    workshop_forms.form:
    path: '/workshop/forms/form'
    defaults:
    _form:
    '\Drupal\workshop_forms\Form\CustomForm’
    _title: 'Workshop Forms Custom Form'
    requirements:
    _permission: 'workshop forms access'
    9

    View Slide

  10. workshop_forms.routing.yml
    workshop_forms.page:
    path: '/workshop/forms/page'
    defaults:
    _controller: '\Drupal\workshop_forms\Controller\WorkshopFormsPageController::hello'
    _title: 'Workshop Forms Page'
    requirements:
    _permission: 'access content'
    RUTAS Y CONTROLADORES EN DRUPAL
    10
    4, si qUIERES JUGAR
    Puedes añadir más rutas al fichero
    Pero recuerda construir un controlador y un método en /src/Controller/

    View Slide

  11. PERMISOS Y MENÚS EN DRUPAL
    5, DEFINIR PERMISOS
    /MODULES/CUSTOM/WORKSHOP_FORMS/
    WORKSHOP_FORMS.PERMISSIONS.YML
    Workshop forms access:
    title: 'Workshop forms access'
    description: 'Access to Workshop form'
    11
    En Drupal el acceso se puede
    gestionar a través de permisos,
    establecidos en un fichero
    declarativo y luego vinculados a
    un rol o a un usuario específico.

    View Slide

  12. PERMISOS Y MENÚS EN DRUPAL
    12
    5, CONSTRUIR MENÚ
    /MODULES/CUSTOM/WORKSHOP_FORMS/
    WORKSHOP_FORMS.LINKS.MENU.YML
    workshop_forms.admin_workshop:
    title: ‘Workshop’
    parent: system.admin
    route_name: workshop_forms.admin_workshop
    description: ‘Links to resources from Workshop’
    weight: -11
    En Drupal 8 la especificación
    de una ruta se mantiene
    desacoplada de la definición
    de un enlace de menú.
    Los gestionamos como
    configuración en un fichero
    propio.

    View Slide

  13. PERMISOS Y MENÚS EN DRUPAL
    5, ELEMENTOS HIJOS
    workshop_forms.forms_view:
    title: 'Workshop Form'
    parent: workshop_forms.admin_workshop
    route_name: workshop_forms.form
    description: 'Showing Workshop Form'
    weight: 1
    workshop_forms.forms_page:
    title: 'Workshop Page'
    parent: workshop_forms.admin_workshop
    route_name: workshop_forms.page
    description: 'Showing Workshop Page'
    weight: 2
    SI QUIERES AMPLIAR CON OTRO ENLACE HIJO
    PERO RECUERDA DEFINIR RUTA Y CONTROLADOR
    13

    View Slide

  14. PERMISOS Y MENÚS EN DRUPAL
    4, AMPLIAMOS ROUTING
    DEFINIMOS UNA RUTA MADRE
    WORKSHOP_FORMS.ROUTING.YML
    workshop_forms.admin_workshop
    path: '/admin/workshop'
    defaults:
    _controller:
    '\Drupal\system\Controller\SystemController::systemAdminMenuBlockPage'
    _title: 'Workshop First Link'
    requirements:
    _access: 'TRUE'
    14

    View Slide

  15. FORMULARIOS EN DRUPAL
    6, FORM API DE DRUPAL
    CONCEPTOS BÁSICOS DE FORMULARIOS
    TIPOS DE FORMULARIOS EN DRUPAL
    1- Basic Form: a normal form of general purpose, adaptable.
    Created from the FormBase Class in Drupal API and maybe the
    most basic kind of form. Class FormBase.php
    2- Config Form: a form of specific use to establish an object
    and configuration values. Created from the ConfigFormBase in
    Drupal API. Class ConfigFormBase.php
    3- Confirm Form: a form to request confirmation from the user
    before executing an irreversible action. Created from the
    ConfigFormBase in Drupal API. Class ConfirmFormBase.php
    15

    View Slide

  16. FORMULARIOS EN DRUPAL
    16
    6, OBJETIVO

    View Slide

  17. FORMULARIOS EN DRUPAL
    6, ELEMENTOS DE FORM
    textarea, radiobuttons, date, range, number,
    button, colorpicker, checkbox, range, select..
    17
    $form['name'] = [
    '#type' => 'textfield',
    '#title' => $this->t('Name'),
    '#description' => $this->t('User Name'),
    '#maxlength' => 64,
    '#weight' => 0,
    ];
    https://api.drupal.org/api/drupal/elements/8.8.x
    https://www.drupal.org/docs/8/api/form-api/form-render-elements
    https://www.drupal.org/docs/develop/user-interface-standards/form-elements

    View Slide

  18. FORMULARIOS EN DRUPAL
    FORMULARIOS EN DRUPAL
    6, BASIC FORM DRUPAL
    /src/Form/CustomForm.php
    namespace Drupal\workshop_forms\Form;
    use Drupal\Core\Form\FormBase;
    use Drupal\Core\Form\FormStateInterface;
    class CustomForm extends FormBase {
    }
    picture from Unsplash, user Mitil - @gigantfotos
    18

    View Slide

  19. FORMULARIOS EN DRUPAL
    6, MÉTODOS BÁSICOS
    RESPONSABILIDADES CLAVE
    public function getFormId() {
    return 'workshop_form';
    }
    public function buildForm(array $form,
    FormStateInterface $form_state) {
    return $form;
    }
    public function validateForm(array &$form,
    FormStateInterface $form_state) {
    }
    public function submitForm(array &$form,
    FormStateInterface $form_state) {
    }
    Devolver el nombre del formulario ->
    Construir el formulario y devolverlo ->
    Validar los valores del formulario ->
    Enviar y procesar valores del formulario ->
    $form -> Formulario, $form_state -> Valores
    19

    View Slide

  20. FORMULARIOS EN DRUPAL
    6, CONSTRUCCIÓN
    20
    $form['name'] = [
    '#type' => 'textfield',
    '#title' => $this->t('Name'),
    '#description' => $this->t('User Name'),
    '#maxlength' => 64,
    '#weight' => 0,
    ];
    $form['id_user'] = [
    '#type' => 'number',
    '#title' => $this->t('User ID'),
    '#description' => $this->t('User ID'),
    '#weight' => 1,
    ];
    $form['email'] = [
    '#type' => 'email',
    '#title' => $this->t('Email'),
    '#description' => $this->t('User email'),
    '#weight' => 2,
    ];
    $form['number_comments'] = [
    '#type' => 'number',
    '#title' => $this->t('Number of Comments'),
    '#description' => $this->t('Number of Comments'),
    '#weight' => 3,
    ];
    $form['types'] = [
    '#type' => 'checkboxes',
    '#title' => $this->t('Content Types'),
    '#description' => $this->t('Select Content Types'),
    '#options' => [1 => '1'],
    '#default_value' => 1,
    '#weight' => 4,
    ];
    $form['submit'] = [
    '#type' => 'submit',
    '#value' => $this->t('Submit'),
    '#weight' => 5,
    ];
    return $form;
    public function buildForm(array $form, FormStateInterface $form_state) { }

    View Slide

  21. COMANDOS ÚTILES EN DRUPAL
    21
    7, ENABLE / DISABLE
    INSTALAR / DESINSTALAR / LIMPIAR CACHÉ
    USANDO DRUSH O DRUPAL CONSOLE
    drush en workshop_forms
    drush cr
    drush pmu workshop_forms
    drupal moi workshop_forms
    drupal mou workshop_forms

    View Slide

  22. INYECCIÓN DE DEPENDENCIAS EN DRUPAL
    8, QUÉ ES UN SERVICIO
    Dependency Injection (DI) es un patrón de diseño orientado a objetos, en el que se suministran objetos a
    una clase en lugar de ser la propia clase la que cree dichos objetos. Nuestras clases no crean los objetos, sino
    que se los suministra otra clase ‘contenedora’ que inyectará la implementación deseada. (Wikipedia).
    Un Service Container (o Dependency Injection container) es un objeto PHP que administra instancias de
    servicios (otros objetos).
    Un Servicio, es en sí mismo una clase que cumple una única responsabilidad, generada de manera única para
    un contexto concreto (Singleton).
    // Antes:
    $servicio = new Foo\Meh\Bah;
    $servicio = Foo\Meh\Bah::getInstance();
    22
    https://www.drupal.org/docs/8/api/services-and-dependency-injection
    https://symfony.com/doc/current/components/dependency_injection.html
    https://www.drupal.org/docs/8/api/services-and-dependency-injection/dependency-injection-for-a-form
    // Ahora:
    $container = $this->getContainer();
    $servicio= $container->get('foo.meh.bah');

    View Slide

  23. INYECCIÓN DE DEPENDENCIAS EN DRUPAL
    8, USO DE SERVICIOS
    DECLARANDO SERVICIOS
    services:
    ban.ip_manager:
    class: Drupal\ban\BanIpManager
    arguments: ['@database']
    tags:
    - { name: backend_overridable }
    ban.middleware:
    class: Drupal\ban\BanMiddleware
    arguments: ['@ban.ip_manager']
    tags:
    - { name: http_middleware, priority: 250 }
    USANDO SERVICIOS DINÁMICAMENTE
    private $database;
    private $current_user;
    public function __construct( Connection $database,
    AccountProxyInterface $current_user ) {
    $this->database = $database;
    $this->current_user = $current_user;
    }
    public static function create(ContainerInterface $container) {
    return new static(
    $container->get('database'),
    $container->get('current_user'),
    );
    }
    USANDO SERVICIOS ESTÁTICAMENTE
    \Drupal::service('module_installer')->uninstall(['action']);
    \Drupal::messenger()->addMessage(‘Message to print’);
    $user = \Drupal::currentUser(); 23
    SERVICIOS DISPONIBLE EN CORE
    CORE.SERVICES.YML

    View Slide

  24. $form['name'] = [
    '#type' => 'textfield',
    '#value' => $this->current_user->getDisplayName(),
    '#title' => $this->t('Name'),
    '#description' => $this->t('User Name'),
    '#maxlength' => 64,
    '#weight' => 0,
    ];
    $form['id_user'] = [
    '#type' => 'number',
    '#value' => $this->current_user->id(),
    '#title' => $this->t('User ID'),
    '#description' => $this->t('User ID'),
    '#maxlength' => 64,
    '#weight' => '1',
    ];
    $form['email'] = [
    '#type' => 'email',
    '#value' => $this->current_user->getEmail(),
    '#title' => $this->t('Email'),
    '#description' => $this->t('User email'),
    '#weight' => '2',
    ];
    PREFILLING DE VALORES EN CAMPOS
    24
    9, PRECARGA EN CAMPO
    USAMOS LOS SERVICIOS INYECTADOS
    PARA COMPLETAR #VALUE

    View Slide

  25. public function validateForm(array &$form, FormStateInterface $form_state) {
    // Get the email value from the field.
    $mail = $form_state->getValue('email');
    // Test the format of the email.
    if(!$this->email_validator->isValid($mail)) {
    $form_state->setErrorByName('email', $this->t('The %email is not valid email.', ['%email' => $mail]));
    }
    }
    PREFILLING DE VALORES EN CAMPOS
    25
    9, USOS DE SERVICIOS
    ADEMÁS DE CAMPOS DE FORMULARIO
    PODEMOS USARLOS EN TODA LA CLASE

    View Slide

  26. composer require drupal/devel
    exec drush en devel devel_generate
    exec drush genc 10 5 --types=article
    CONSULTAS DINÁMICAS A LA BASE DE DATOS
    26
    10, PREPARANDO NODOS
    INSTALAMOS Y HABILITAMOS DEVEL
    GENERAMOS CONTENIDO

    View Slide

  27. // Build the base query.
    $query = $this->database->select('comment_field_data', 'c')
    ->fields('c')
    ->condition('c.uid', $this->currentUser->id(), '=');
    // Get the number of registers.
    $query_counter = $query->countQuery();
    $result = $query_counter->execute();
    $count = $result->fetchField();
    // Using the count value for prefilling the value.
    $form['number_comments'] = [
    '#type' => 'number',
    '#value' => $count,
    '#title' => $this->t('Number of Comments'),
    '#description' => $this->t('Number of Coments'),
    '#weight' => 3,
    ];
    CONSULTAS DINÁMICAS A BASE DE DATOS
    27
    10, CONSULTA Y CARGA
    EN DRUPAL PODEMOS USAR
    CONSULTAS ESTÁTICAS O DINÁMICAS
    // Consultas estáticas.
    $database = \Drupal::database();
    $query = $database->query("SELECT id,
    example FROM {mytable}");
    $result = $query->fetchAll();
    https://www.drupal.org/docs/8/api/datab
    ase-api/static-queries

    View Slide

  28. $options = node_type_get_names();
    $defaults = array_keys($options);
    $form['types'] = [
    '#type' => 'checkboxes',
    '#title' => $this->t('Content Types'),
    '#description' => $this->t('Select Content
    Types'),
    '#options' => $options,
    '#default_value' => $defaults,
    '#weight' => '4',
    ];
    PREFILLING DE VALORES EN CAMPOS
    28
    9, OTROS ORÍGENES
    Hemos visto cómo precargar valores en
    campos a lo largo de diversos ejemplos
    para nuestros campos de formulario
    basado en la Form API de Drupal:
    hemos usado servicios bajo el modelo de
    Inyección de Dependencias (DI) de
    Symfony y también hemos realizado
    consultas directas a la base de datos
    través de la Database API de Drupal.
    Ahora veremos otro origen de datos más a
    partir del que podemos extraer
    información: simples funciones
    pre-existentes.

    View Slide

  29. FORMULARIOS EN DRUPAL
    29
    6, ALTERANDO EL FORM
    if(!$this->current_user->isAuthenticated()) {
    $form['help'] = [
    '#type' => 'item',
    '#title' => $this->t('Please, read the conditions.'),
    '#markup' => $this->t('Only for registered users.'),
    ];
    }else {
    $form['email'] = [
    '#type' => 'email',
    '#value' =>
    $this->current_user->getEmail(),
    '#title' => $this->t('Email'),
    '#description' => $this->t('User email'),
    '#weight' => '2',
    ];
    $form['submit'] = [
    '#type' => 'submit',
    '#value' => $this->t('Submit'),
    '#weight' => 5,
    ];
    }
    No debemos perder de vista que en realidad, nunca nos hemos movido del contexto propio de
    una Clase PHP y un método buildForm(). Así que vamos a jugar con algunas cláusulas if - else.

    View Slide

  30. FORMULARIOS EN DRUPAL
    30
    6, RESULTADOS

    View Slide

  31. INYECCIÓN DE DEPENDENCIAS EN DRUPAL
    31
    public function validateForm(array &$form, FormStateInterface $form_state) {
    // Get the email value from the field.
    $mail = $form_state->getValue('email');
    // Test the format of the email.
    if(!$this->email_validator->isValid($mail)) {
    $form_state->setErrorByName('email', $this->t('The %email is not a valid email.', ['%email' => $mail]));
    }
    }
    public function submitForm(array &$form, FormStateInterface $form_state) {
    // Display result in submit.
    foreach ($form_state->getValues() as $key => $value) {
    \Drupal::messenger()->addMessage($key . ': ' . ($key === 'text_format'?$value['value']:$value));
    }
    }
    INYECCIÓN DE DEPENDENCIAS EN DRUPAL
    8, VALIDACIÓN GLOBAL
    USAR SERVICIOS PARA VALIDACIONES
    EN MÉTODOS VALIDATEFORM O SUBMIT

    View Slide

  32. $form['titulo'] = [
    '#type' => 'textfield',
    '#title' => $this->t('Título'),
    '#description' => $this->t('Titulo en el formulario.'),
    '#required' => TRUE,
    '#weight' => '0',
    '#element_validate' => ['::titleCustomValidation'],
    ];
    public function titleCustomValidation($element, FormStateInterface $form_state) {
    // Insert new custom conditions for valitions in the ‘titulo’ field.
    $form_state->setErrorByName('titulo', $this->t($error_message));
    }
    PREFILLING DE VALORES EN CAMPOS
    32
    INYECCIÓN DE DEPENDENCIAS EN DRUPAL
    INYECCIÓN DE DEPENDENCIAS EN DRUPAL
    8, VALIDACIÓN CUSTOM
    ES POSIBLE USAR VALIDACIONES CUSTOM
    ESPECÍFICAS PARA CADA CAMPO DE FORM

    View Slide

  33. Modo interactivo
    drupal generate:module
    drupal gm
    COMANDOS ÚTILES EN DRUPAL
    33
    7, CREAR MÓDULOS
    CREACIÓN AUTOMÁTICA
    USANDO DRUPAL CONSOLE
    Modo no interactivo
    drupal generate:module \
    --module="My Random module" \
    --machine-name="my_random_module" \
    --module-path="modules/custom" \
    --description="Random generated custom module" \
    --core="8.x" \
    --package="Custom" \
    --module-file \
    --no-interaction

    View Slide

  34. Modo interactivo
    drupal generate:form
    drupal gf
    Modo no interactivo
    drupal generate:form \
    --module="my_random_module" \
    --class="RandomClassForm" \
    --form-id="default_random_form" \
    --config-file \
    --inputs='"name":"name", "type":"textfield", "label":"Name", "options":"", "description":"User Name", "maxlength":"64", "size":"",
    "default_value":"", "weight":"0", "fieldset":""' \
    --inputs='"name":"id_user", "type":"number", "label":"User ID", "options":"", "description":"User ID", "maxlength":"64", "size":"",
    "default_value":"", "weight":"1", "fieldset":""' \
    --inputs='"name":"email", "type":"email", "label":"Email", "options":"", "description":"User email", "maxlength":"", "size":"", "default_value":"",
    "weight":"2", "fieldset":""' \
    --inputs='"name":"number_comments", "type":"number", "label":"Number of Comments", "options":"", "description":"Number of Coments",
    "maxlength":"", "size":"", "default_value":"", "weight":"3", "fieldset":""' \
    --inputs='"name":"types", "type":"checkboxes", "label":"Content Types", "options":"['1' => '1']", "description":"Select Content Types",
    "maxlength":"", "size":"", "default_value":"1", "weight":"4", "fieldset":""' \
    --path="/my_random_module/forms/random_form" \
    --no-interaction
    COMANDOS ÚTILES EN DRUPAL
    34
    7, CREAR FORMULARIOS

    View Slide

  35. drupal generate:form \
    --module="my_random_module" \
    --class="RandomClassForm" \
    --form-id="default_random_form" \
    --config-file \
    --inputs='"name":"name", "type":"textfield", "label":"Name", "options":"", "description":"User Name", "maxlength":"64", "size":"",
    "default_value":"", "weight":"0", "fieldset":""' \
    --inputs='"name":"id_user", "type":"number", "label":"User ID", "options":"", "description":"User ID", "maxlength":"64", "size":"",
    "default_value":"", "weight":"1", "fieldset":""' \
    --inputs='"name":"email", "type":"email", "label":"Email", "options":"", "description":"User email", "maxlength":"", "size":"",
    "default_value":"", "weight":"2", "fieldset":""' \
    --inputs='"name":"number_comments", "type":"number", "label":"Number of Comments", "options":"", "description":"Number
    of Coments", "maxlength":"", "size":"", "default_value":"", "weight":"3", "fieldset":""' \
    --inputs='"name":"types", "type":"checkboxes", "label":"Content Types", "options":"['1' => '1']", "description":"Select Content
    Types", "maxlength":"", "size":"", "default_value":"1", "weight":"4", "fieldset":""' \
    --path="/my_random_module/forms/random_form" \
    --services="database" \
    --services="current_user" \
    --services="email.validator" \
    --no-interaction
    COMANDOS ÚTILES EN DRUPAL
    35
    7, FORMS + SERVICIOS

    View Slide

  36. “Hacia rutas salvajes” (Routing en Drupal 8) by @jansete
    https://docs.google.com/presentation/d/17KVjfmgMtIIIDl0N40Vm1iyaUBg27mGE1hV2byIR4OM/edit
    “Structure of routes” (Drupal 8 documentation)
    https://www.drupal.org/docs/8/api/routing-system/structure-of-routes
    Let’s take the best route - Exploring Drupal 8 routing system
    https://www.srijan.net/blog/exploring-drupal-8-routing-system
    Using Links in Drupal 8
    https://davidjguru.github.io/blog/drupal-fast-tips-using-links-in-drupal-8
    Formularios en Drupal 8 (Crear formularios, modificar formularios, ejemplos con Hooks)
    https://medium.com/drupal-y-yo/form-api-i-comprender-crear-y-modificar-formularios-en-drupal-8-22c0cf4d72d3
    https://medium.com/drupal-y-yo/form-api-ii-modificando-formularios-en-drupal-8-mediante-form-alter-78fa949b43d0
    https://medium.com/drupal-y-yo/form-api-iii-caso-pr%C3%A1ctico-de-modificaci%C3%B3n-de-formulario-en-drupal-8-f8ab4dd40a5c
    Prefilling fields in forms (Precargando campos en formularios)
    https://davidjguru.github.io/blog/drupal-fast-tips-prefilling-fields-in-forms
    LECTURAS RECOMENDADAS
    36
    11, AMPLIA INFORMACIÓN

    View Slide

  37. https://gitlab.com/davidjguru/drupal-custom-modules-examples/tree/master/my_random_module
    DESPEDIDA Y CIERRE
    37
    12, EVERY TIME WE SAY GOODBYE
    Recuerda que puedes escribirme a [email protected] y aquí tienes el código disponible:
    In memory of
    En recuerdo de

    View Slide