logo

Extra Block Types (EBT) - Nieuwe Layout Builder ervaring❗

Extra Block Types (EBT) - gestileerde, aanpasbare bloktypes: Slideshows, Tabs, Cards, Accordions en vele andere. Ingebouwde instellingen voor achtergrond, DOM Box, javascript-plugins. Ervaar vandaag al de toekomst van layout building.

Demo EBT-modules Download EBT-modules

❗Extra Paragraph Types (EPT) - Nieuwe Paragraphs ervaring

Extra Paragraph Types (EPT) - analoge op paragrafen gebaseerde set modules.

Demo EPT-modules Download EPT-modules

Scroll

Een 500-foutpagina toevoegen in Drupal met behulp van een Event Subscriber

02/09/2025, by Ivan

Menu

Vaak krijgen we een 500-foutpagina te zien wanneer Drupal, services of andere sites niet beschikbaar zijn. Wanneer we een 500- (of 501–504-)foutpagina zien, gebruikt Drupal uitzonderingen (Exceptions) om te controleren of kritieke code is uitgevoerd. Als er bijvoorbeeld een fout optreedt bij een HTTP-verzoek naar een andere site, toont Drupal deze foutmelding: "De website ondervond een onverwachte fout. Probeer het later opnieuw.":

Standaard 500-foutpagina van Drupal
Standaard 500-foutpagina van Drupal

Het is niet wenselijk om een WSOD (white screen of death) op je site te hebben, dus laten we dit verbeteren en een gestileerde HTML-pagina tonen.

Ik heb een gestileerde 500.html-pagina in de root van mijn site geplaatst omwille van prestaties. We kunnen een Drupal-pagina gebruiken voor fout 500, maar ik wil dezelfde pagina ook hergebruiken voor 503/504-fouten in Apache/Nginx. Daarom is het gemakkelijker om deze pagina op één centrale plek als een los HTML-bestand te bewaren.

500 HTML-pagina
500 HTML-foutpagina

Nu voegen we de code toe aan onze aangepaste module DrupalBook Custom (drupalbook_custom). In drupalbook_custom.services.yml voegen we de Event Subscriber toe:

services:
  drupalbook_custom.exception_subscriber:
    class: Drupal\drupalbook_custom\EventSubscriber\SeoExceptionSubscriber
    arguments: ['@config.factory']
    tags:
      - { name: event_subscriber, priority: -250 }

Hier is de code voor drupalbook_custom/src/EventSubscriber/SeoExceptionSubscriber:

<?php

namespace Drupal\drupalbook_custom\EventSubscriber;

use Drupal\Component\Render\FormattableMarkup;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Render\Markup;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\Utility\Error;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
use Symfony\Component\HttpKernel\KernelEvents;

/**
 * Vervangt de standaard 500-foutafhandeling van Drupal.
 */
class SeoExceptionSubscriber implements EventSubscriberInterface {

  use StringTranslationTrait;

  protected ConfigFactoryInterface $configFactory;

  public function __construct(ConfigFactoryInterface $config_factory) {
    $this->configFactory = $config_factory;
  }

  public function onException(ExceptionEvent $event): void {
    if ($this->isErrorLevelVerbose()) {
      return;
    }

    $exception = $event->getThrowable();

    $error = Error::decodeException($exception);
    $message = new FormattableMarkup('@message', [
      '@message' => $error['!message'] ?? $this->t('De website ondervond een onverwachte fout.'),
    ]);

    $html = $this->buildHtml((string) $message);
    $status = $exception instanceof HttpExceptionInterface
      ? $exception->getStatusCode()
      : Response::HTTP_INTERNAL_SERVER_ERROR;

    $response = new Response($html, $status, ['Content-Type' => 'text/html']);

    if ($exception instanceof HttpExceptionInterface) {
      $response->headers->add($exception->getHeaders());
    }

    $event->setResponse($response);
    $event->stopPropagation();
  }

  protected function buildHtml(string $message): string {
    $template = DRUPAL_ROOT . '/500.html';

    if (is_readable($template)) {
      $html = file_get_contents($template);
      return str_replace('{{ message }}', Markup::create($message), $html);
    }

    return '<html><head><title>500</title></head><body>'
      . Markup::create($message)
      . '</body></html>';
  }

  protected function isErrorLevelVerbose(): bool {
    return $this->configFactory
      ->get('system.logging')
      ->get('error_level') === ERROR_REPORTING_DISPLAY_VERBOSE;
  }

  public static function getSubscribedEvents(): array {
    $events[KernelEvents::EXCEPTION][] = ['onException', -250];
    return $events;
  }

}

Deze subscriber-klasse, SeoExceptionSubscriber, onderschept alle ongecontroleerde uitzonderingen binnen Drupal. Als de foutloginstelling op "verbose" staat, toont Drupal zijn standaardfoutmeldingen. In productieomgevingen, waar deze modus meestal uit staat, toont deze klasse in plaats daarvan een gebruikersvriendelijke HTML-foutpagina.

Specifiek leest het een aangepaste 500.html-pagina uit de root van de Drupal-installatie, en vervangt een placeholder {{ message }} door het daadwerkelijke foutbericht. Zo blijft de foutpagina visueel aantrekkelijk en informatief.

Daarnaast stopt de subscriber expliciet verdere foutafhandeling door Drupal core, zodat jouw aangepaste HTML-pagina niet wordt overschreven. Met prioriteit -250 wordt deze subscriber uitgevoerd net vóór de standaard foutsubscriber van Drupal (die prioriteit -256 heeft).

Voor lokale omgevingen kun je instellen dat fouten wél getoond worden in plaats van de 500-pagina:
settings.php:

$config['system.logging']['error_level'] = 'verbose';

error_reporting(E_ALL);
ini_set('display_errors', TRUE);
ini_set('display_startup_errors', TRUE);

Soms is Drupal helemaal niet bereikbaar, dan is aanvullende configuratie op je webserver of in de cloud nodig.

500-foutpagina instellen in Apache

Om je bestaande 500.html-pagina te serveren bij HTTP-fouten 500–504, voeg je de volgende regels toe aan je Apache-configuratie:

1. Via Apache Virtual Host-configuratie (aanbevolen)

ErrorDocument 500 /500.html
ErrorDocument 501 /500.html
ErrorDocument 502 /500.html
ErrorDocument 503 /500.html
ErrorDocument 504 /500.html

Herlaad daarna Apache:

sudo systemctl reload apache2

2. Via het .htaccess-bestand

Voeg deze regels toe aan het .htaccess-bestand in de root van je site:

ErrorDocument 500 /500.html
ErrorDocument 501 /500.html
ErrorDocument 502 /500.html
ErrorDocument 503 /500.html
ErrorDocument 504 /500.html

Zorg ervoor dat 500.html leesbaar is voor Apache. Nu zal Apache deze pagina tonen bij 500–504-fouten.

500-foutpagina instellen in Nginx

Om Nginx je aangepaste 500.html-foutpagina te laten tonen bij fouten 500–504, voeg je de volgende configuratie toe in het server {}-blok van je siteconfiguratie:

error_page 500 501 502 503 504 /500.html;
location = /500.html {
    root /var/www/html;
    internal;
}

Zorg dat het pad (/var/www/html) verwijst naar je site root waarin 500.html zich bevindt. Herlaad daarna Nginx:

sudo nginx -s reload

Vanaf nu toont Nginx je eigen HTML-foutpagina bij serverfouten van 500 t/m 504.