Crear bloques por código en Drupal 8

En Drupal los bloques son una de las principales herramientas de que disponemos para mostrar distintos componentes o contenidos, y colocarlos en la página en distintas posiciones. Drupal viene con una serie de bloques por defecto, y cada módulo puede definir sus propios bloques, así que una de las cosas básicas de trabajar con Drupal pasa por aprender a crear nuestros propios bloques. 

Empezaremos por lo básico y luego lo complicaremos un poco para tocar algunos conceptos más interesantes.

 

Creando un bloque sencillo

Lo primero que vamos a necesitar es crear un nuevo módulo (o utilizar uno que ya tengamos) e instalarlo, para tener un sitio donde meter nuestro código.

En Drupal 8 todos los bloques son instancias de la clase Plugin, y el gestor de bloques (Block manager) se encargará de encontrar los bloques que hayamos definido por medio de anotaciones de PHP en nuestras clases.

Primero crearemos la clase para nuestro bloque en un archivo dentro de nuestro módulo, que deberá estar en el directorio

src/Plugin/Block

El nombre del archivo debe coincidir con el nombre de la clase, o no funcionará. Por ejemplo, vamos a crear un bloque HolaMundo, por lo que crearemos el siguiente archivo:

src/Plugin/Block/HolaMundo.php

Con el siguiente código:

<?php

namespace Drupal\hola_mundo\Plugin\Block;

use Drupal\Core\Block\BlockBase;

/**
 * Clase de control del bloque HolaMundo.
 *
 * @Block(
 *   id = "hola_mundo",
 *   admin_label = @Translation("Hola mundo"),
 *   category = @Translation("Hola mundo"),
 * )
 */
class HolaMundo extends BlockBase {

  /**
   * {@inheritdoc}
   */
  public function build() {
    return [
      '#markup' => $this->t('Hola mundo!'),
    ];
  }

}

 

Ahora debemos limpiar la caché, y ya podremos añadir nuestro nuevo bloque a una página desde el menú Estructura > Diseño de bloques, y colocarlo en la región que queramos.

Como veis, nuestra clase extenderá de BlockBase, debemos poner las anotaciones de PHP (id, admin_label y category), y solamente tenemos que implementar el método build() que tiene que devolver un array para ser renderizado. Si utilizamos #markup, podemos devolver ahi todo el código HTML que queramos que pinte nuestro bloque.

 

Usando templates para nuestros bloques

Como en la mayoría de los casos lo que queremos pintar en el bloque no será algo tan sencillo como este ejemplo, es buena idea definir un template, de forma que podamos separar la lógica de la presentación, y evitemos tener que meter todo el HTML de esta forma dentro de #markup, que es bastante poco elegante, por decir algo suave.

Configurar un template o plantilla para nuestro nuevo bloque es bastante sencillo. La forma mas simple no requiere prácticamente nada, y aunque he visto muchos ejemplos donde dicen que es necesario implementar un hook_theme(), esto no es estrictamente necesario.

Primero vamos a hacer unas modificaciones en nuestra función build() del bloque que acabamos de crear para pasarle algunas variables al template, y evitar meter código HTML en nuestras clases PHP. Ahora en vez de devolver todo dentro de #markup, pasaremos distintas variables a las que asignamos el nombre que queramos, en este caso serán title y description, pero podemos llamarlas como queramos: 

/**
 * {@inheritdoc}
 */
public function build() {

  return [
    'title' => t('Hola mundo!'),
    'description' => t('Esto es un bloque que pinta un hola mundo'),
  ];
}

Listo, sigamos adelante. Solamente con lo que tenemos hasta ahora, Drupal asignará por defecto ciertos templates para aplicar a nuestro bloque. Si activamos el theme debug, podremos ver los nombres de fichero que Drupal buscará dentro del tema que tengamos activo, que para nuestro caso son estos:

<!-- FILE NAME SUGGESTIONS:
   * block--holamundo.html.twig
   * block--hola-mundo.html.twig
   * block--mimodulo.html.twig
   x block.html.twig
-->

Drupal utilizará el template de bloque por defecto block.html.twig cuando ninguno de esos otros ficheros existe.

Entonces solo tenemos que crear el archivo de template para el bloque dentro de nuestro tema, usando alguno de esto nombres para el fichero. Es buena idea crear un directorio dentro del tema llamado templates/block, para tenerlos mejor organizados:

themes/custom/nuestro_tema/templates/block/block--hola-mundo.html.twig

Y dentro de este template utilizaremos las variables que hemos definido en build() para mostrar la información:

{#
/**
 * @file
 * Hola mundo block.
 */
#}
<div class="wrapper hola-mundo--block">
  <h1>{{ content.title }}</h1>
  <p>{{ content.description }}</p>
</div>

Importante aquí que nuestras variables deben prefijarse con content.nombre_de_variable, o no veremos ningún resultado.

No queda más que borrar caches y probar nuestro nuevo bloque.