logo

Dodatni tipovi blokova (EBT) - Novo iskustvo rada sa Layout Builder-om❗

Dodatni tipovi blokova (EBT) – stilizovani, prilagodljivi tipovi blokova: slajdšouvi, kartice sa tabovima, kartice, akordeoni i mnogi drugi. Ugrađena podešavanja za pozadinu, DOM Box, javascript dodatke. Iskusite budućnost kreiranja rasporeda već danas.

Demo EBT moduli Preuzmite EBT module

❗Dodatni tipovi pasusa (EPT) – Novo iskustvo rada sa pasusima

Dodatni tipovi pasusa (EPT) – analogni skup modula zasnovan na pasusima.

Demo EPT moduli Preuzmite EPT module

Scroll

Dodavanje stranice za grešku 500 u Drupalu pomoću Event Subscriber-a

11/06/2025, by Ivan

Menu

Često se suočavamo sa stranicom greške 500 kada Drupal, servisi ili drugi sajtovi nisu dostupni. Kada vidimo grešku 500 (ili 501–504). U Drupalu koristimo Exceptions da proverimo da li je neki kritičan kod izvršen. Ako dođe do greške, na primer pri HTTP zahtevu ka drugom sajtu, Drupal će prikazati ovu grešku: "The website encountered an unexpected error. Please try again later":

Drupal default 500 error page
Drupal default 500 error page

Nije dobro imati WSOD (white screen of death) na svom sajtu, zato hajde da to poboljšamo i prikažemo stilizovanu HTML stranicu umesto toga.

Imam stilizovanu 500.html stranicu u root folderu sajta, iz performansnih razloga. Možemo koristiti i stilizovanu Drupal stranicu za 500 grešku, ali takođe koristim istu stranicu i za 503/504 greške u Apache/Nginx i lakše je održavati ovu stranicu kao jedan HTML fajl na jednom mestu.

500 HTML page
500 HTML error page

Sada treba da dodamo kod u naš prilagođeni modul DrupalBook Custom (drupalbook_custom). U drupalbook_custom.services.yml treba da dodamo Event Subscriber:

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

Ovde je kod za 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;

/**
 * Zamenjuje Drupal\Core\EventSubscriber\FinalExceptionSubscriber 500 grešku.
 */
class SeoExceptionSubscriber implements EventSubscriberInterface {

  use StringTranslationTrait;

  /**
   * Konfiguracija za podešavanja.
   *
   * @var \Drupal\Core\Config\ConfigFactoryInterface
   */
  protected ConfigFactoryInterface $configFactory;

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

  /**
   * Obradjuje sve neuhvaćene exception-e i vraća prilagođeni HTML odgovor.
   */
  public function onException(ExceptionEvent $event): void {
    // Prikazati standardni Drupal stack trace kada je sajt u VERBOSE režimu.
    if ($this->isErrorLevelVerbose()) {
      return;
    }

    $exception = $event->getThrowable();

    // Osnovna poruka (proširiti za verbose režim ako treba).
    $error = Error::decodeException($exception);
    $message = new FormattableMarkup('@message', [
      '@message' => $error['!message'] ?? $this->t('The website encountered an unexpected error.'),
    ]);

    $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']);

    // Sačuvati dodatne zaglavlja kao što je Retry-After ako su prisutna.
    if ($exception instanceof HttpExceptionInterface) {
      $response->headers->add($exception->getHeaders());
    }

    // Pošalji odgovor i zaustavi dalje Event Subscriber-e (uključujući core).
    $event->setResponse($response);
    $event->stopPropagation();
  }

  /**
   * Čita web/500.html i ubacuje {{ message }} token ako postoji.
   */
  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);
    }

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

  /**
   * TRUE kada je nivo greške podešen na “Verbose”.
   *
   * Ogledalo \Drupal\Core\EventSubscriber\FinalExceptionSubscriber::isErrorLevelVerbose().
   */
  protected function isErrorLevelVerbose(): bool {
    return $this->configFactory
      ->get('system.logging')
      ->get('error_level') === ERROR_REPORTING_DISPLAY_VERBOSE;
  }

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents(): array {
    // Prioritet -250 → izvršava se neposredno pre core FinalExceptionSubscriber (-256).
    $events[KernelEvents::EXCEPTION][] = ['onException', -250];
    return $events;
  }

}

Ova subscriber klasa, SeoExceptionSubscriber, presreće sve neuhvaćene exception-e unutar Drupala. Proverava da li je vaš Drupal sajt podešen na detaljni prikaz grešaka (verbose mode), i ako jeste, dozvoljava Drupalu da prikaže svoje standardne detaljne poruke o grešci. Međutim, ako sajt nije u verbose režimu (što je tipično za produkciju), presreće exception i priprema korisniku prijatniju poruku o grešci.

Konkretno, čita vaš prilagođeni 500.html fajl koji se nalazi u root folderu vaše Drupal instalacije. Dinamički ubacuje poruku o grešci u HTML sadržaj tako što zamenjuje placeholder {{ message }}, osiguravajući da prikazana stranica bude informativna i vizuelno dosledna.

Dodatno, subscriber eksplicitno sprečava Drupal-ov podrazumevani handler za greške da dalje procesira događaj. Ovo osigurava da Drupal-ova ugrađena error stranica ne prepiše vaš prilagođeni HTML. Definisanjem subscriber-a sa prioritetom -250, izvršava se neposredno pre ugrađenog Drupal error subscriber-a, efektivno nadjačavajući Drupal-ovo podrazumevano ponašanje.

Za lokalno okruženje možete dodati podešavanja za prikazivanje grešaka umesto 500 error strane.
settings.php:

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

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

Ponekad Drupal nije dostupan, pa će biti potrebno da dodatno podesite vaš web server ili Cloud okruženje.

Dodavanje 500 error strane u Apache

Da biste prikazali postojeću 500.html stranicu iz root direktorijuma vašeg sajta svaki put kada dođe do HTTP grešaka 500–504, potrebno je podesiti Apache. Evo dva jednostavna načina za to:

1. Korišćenje Apache Virtual Host konfiguracije (preporučeno)

Izmenite konfiguracioni fajl vašeg sajta (najčešće /etc/apache2/sites-available/your-site.conf) i dodajte sledeće direktive unutar <VirtualHost> bloka:

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

Zatim restartujte Apache da bi se promene primenile:

sudo systemctl reload apache2

2. Korišćenje .htaccess fajla

Ako želite da koristite .htaccess fajl (u root direktorijumu sajta), dodajte sledeće linije:

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

Uverite se da je fajl 500.html postavljen u root direktorijumu sajta i da je Apache može pročitati. Nakon ovih podešavanja, Apache će prikazivati vašu stilizovanu HTML error stranicu za greške od 500 do 504.

Dodavanje 500 error strane u Nginx

Da biste podesili Nginx da prikazuje vašu prilagođenu 500.html stranicu iz root direktorijuma sajta za HTTP greške (500–504), izmenite Nginx konfiguraciju vašeg sajta na sledeći način:

Otvorite konfiguracioni fajl vašeg sajta (najčešće /etc/nginx/sites-available/your-site.conf) i dodajte sledeće direktive unutar server {} bloka:

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

Proverite da li /var/www/html odgovara root direktorijumu vašeg sajta gde se nalazi 500.html. Nakon izmena, restartujte Nginx da bi se promene primenile:

sudo nginx -s reload

Sada će Nginx prikazivati vašu prilagođenu HTML stranicu za greške od 500 do 504.