Obtener el nodo que se visualiza desde un bloque

Imagen
Globo flotando en nubes

Recientemente en un proyecto, necesite obtener el nodo que se estaba visualizando para cargar en un bloque otros nodos relacionados. Con Views no era posible, ya que exigía una relación compleja y cargar otras entidades, a si que tuve que hacerlo manualmente.

El proceso no es complicado, realmente, solo necesitamos una línea para poder obtener el nodo, pero si que puede complicarse un poco con validaciones y dar ciertos problemas si no se realiza correctamente.

Para obtenerlo necesitamos el servicio “request_stack” y se obtiene de la siguiente manera:

$this->request->attributes->get('node');

Con esa línea, obtenemos el objeto nodo de los atributos de la petición actual.

El proceso completo para obtener el nodo:

Ahora veremos todo el proceso de validación y uso de caches para que todo funcione correctamente.

Primero vamos a crear un método para poder obtener el nodo, esto es debido a que vamos a cargarlo en varias ocasiones, a si que mejor separarlo.

protected function getNode() {
    $node = $this->request->attributes->get('node');
    if (!$node instanceof NodeInterface) {
      throw new \UnexpectedValueException("Not a node page");
    }
    return $node;
  }

Ahora, tenemos que validar el acceso, para que el bloque no se muestre en caso de que no se haya obtenido ningún nodo.

protected function blockAccess(AccountInterface $account) {
    try {
      $node = $this->getNode();
    }
    catch (\UnexpectedValueException $ex) {
      return AccessResult::forbidden();
    }
    return parent::blockAccess($account);
  }

Ya casi estamos, ahora vamos a añadirle la cache para optimizar esto.

public function getCacheTags() {
    $node = $this->getNode();
    return Cache::mergeTags(parent::getCacheTags(), $node->getCacheTags());
  }

  public function getCacheContexts() {
    return Cache::mergeContexts(parent::getCacheContexts(), ['route']);
  }

Y listo, ya solo nos queda devolver el titulo del nodo que tenemos para poder crear el contenido del bloque:

public function build() {
    $build = [
      '#markup' => $this->getNode()->label(),
    ];
    return $build;
  }

Y listo, esto es todo, es algo muy sencillo de hacer, pero lo dicho, lo complicado, es la pequeña validación que hay que hacer para que funcione correctamente.

Obtener el nodo en un bloque

Por último, dejo el código de ejemplo para descargar, por si alguien lo quiere tener completo.

Archivo

Artículos relacionados: