Widoki w PHP - Kompleksowy Przewodnik po Twig

08.09.2025

Widoki w PHP - Kompleksowy Przewodnik po Twig

Czym są widoki w aplikacjach PHP?

Widoki stanowią warstwę prezentacji w architekturze MVC (Model-View-Controller). Odpowiadają za renderowanie danych i generowanie HTML wysyłanego do przeglądarki użytkownika. W kursie PHP 8.4 prezentujemy kompleksowe podejście do budowania systemu widoków - od integracji z gotowymi silnikami renderującymi jak Twig, przez implementację własnego silnika inspirowanego Blade, aż po nowoczesne SPA z Inertia.js i Vue 3.

Dlaczego warto nauczyć się systemu widoków?

Kluczowe korzyści

  • Separacja logiki biznesowej od warstwy prezentacji
  • Możliwość współpracy programistów z projektantami
  • Wielokrotne wykorzystanie komponentów UI (DRY principle)
  • Zwiększenie bezpieczeństwa dzięki automatycznemu escapowaniu

Twig - Popularny Silnik Szablonów

Twig to jeden z najpopularniejszych silników szablonów w ekosystemie PHP. Został zaprojektowany z myślą o prostocie, elastyczności i wydajności. W kursie dowiesz się, jak zintegrować Twig z własnym frameworkiem poprzez stworzenie adaptera zgodnego z wzorcami projektowymi.

Główne zalety Twig

  • Elastyczność - możliwość tworzenia niestandardowych rozszerzeń i funkcji
  • Wydajność - widoki kompilowane do zoptymalizowanego kodu PHP
  • Bezpieczeństwo - automatyczne escapowanie zmiennych
  • Czytelność - składnia zaprojektowana dla projektantów

Podstawowa składnia Twig

<!DOCTYPE html>
<html>
<head>
    <title>{{ title }}</title>
</head>
<body>
    <h1>Witaj, {{ name|capitalize }}!</h1>

    {% if user.isLoggedIn %}
        <p>Zalogowany jako: {{ user.email }}</p>
    {% else %}
        <p>Proszę się zalogować.</p>
    {% endif %}

    <ul>
    {% for post in posts %}
        <li>{{ post.title }} - {{ post.created_at|date("d-m-Y") }}</li>
    {% endfor %}
    </ul>
</body>
</html>

Architektura systemu widoków w kursie

W kursie PHP 8.4 budujesz kompletny, modularny system widoków składający się z kilku kluczowych komponentów:

1. Adapter Twig - Integracja z silnikiem

TwigRendererAdapter implementuje interfejs adaptera i wykorzystuje klasę Twig\Environment do renderowania widoków. Adapter odpowiada za:

  • Renderowanie szablonów z przekazanymi danymi
  • Zarządzanie pamięcią podręczną (cache)
  • Konfigurację środowiska (development/production)
<?php
class TwigRendererAdapter extends BaseAdapter implements RendererInterface
{
    public function __construct(
        private readonly Environment $twig,
        private readonly string $cacheDir
    ) {}

    public function render(string $template, array $data = []): string
    {
        return $this->twig->render($template, $data);
    }

    public static function buildDefault(): self
    {
        $config = config('views.twig');
        $loader = new FilesystemLoader($config['paths']);
        $twig = new Environment($loader, [
            'cache' => $config['cache'],
            'auto_reload' => $config['auto_reload'],
        ]);

        return new self($twig, $config['cache']);
    }
}

2. Klasa View - Abstrakcja nad rendererami

Klasa View pełni rolę pośrednika między kontrolerem a adapterem renderującym. Implementuje wzorzec projektowy Facade, upraszczając interfejs do renderowania widoków.

<?php
class View
{
    public function __construct(
        private readonly RendererInterface $renderer,
        private readonly string $template,
        private array $data = []
    ) {}

    public function with(string|array $key, mixed $value = null): self
    {
        if (is_array($key)) {
            $this->data = array_merge($this->data, $key);
        } else {
            $this->data[$key] = $value;
        }
        return $this;
    }

    public function render(): ResponseInterface
    {
        $content = $this->renderer->render($this->template, $this->data);
        return new Response(body: $content);
    }
}

3. Integracja w kontrolerze

Bazowa klasa Controller zapewnia wygodne metody do renderowania widoków. Możesz w łatwy sposób zmienić domyślny renderer dla konkretnego kontrolera.

<?php
abstract class Controller
{
    protected ViewManager $viewManager;
    protected string $defaultRenderer = 'twig';

    public function __construct(ViewManager $viewManager)
    {
        $this->viewManager = $viewManager;
    }

    protected function render(string $template, array $data = []): ResponseInterface
    {
        return $this->viewManager
            ->withRenderer($this->defaultRenderer)
            ->make($template, $data)
            ->render();
    }

    protected function withRenderer(string $renderer): self
    {
        $this->defaultRenderer = $renderer;
        return $this;
    }
}

Layouty i dziedziczenie w Twig

Twig umożliwia tworzenie layoutów, które mogą być wspólne dla wielu szablonów. Layout to szkielet HTML z zdefiniowanymi sekcjami do wypełnienia.

Przykładowy layout (layouts/app.twig)

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>{% block title %}Moja aplikacja{% endblock %}</title>
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
  {% block styles %}{% endblock %}
</head>
<body>
  <nav >
    <div >
      <a href="/">MasterPHP</a>
    </div>
  </nav>

  <main >
    {% block content %}{% endblock %}
  </main>

  <footer >
    <div >
      {% block footer %}
        <p>&copy; 2025 MasterPHP</p>
      {% endblock %}
    </div>
  </footer>

  {% block scripts %}{% endblock %}
</body>
</html>

Widok wykorzystujący layout (home.twig)

{% extends "layouts/app.twig" %}

{% block title %}Strona główna - MasterPHP{% endblock %}

{% block content %}
  <h1>{{ pageTitle }}</h1>
  <p>{{ welcomeMessage }}</p>

  <div >
    {% for feature in features %}
    <div >
      <div >
        <div >
          <h5 >{{ feature.title }}</h5>
          <p >{{ feature.description }}</p>
        </div>
      </div>
    </div>
    {% endfor %}
  </div>
{% endblock %}

{% block scripts %}
  <script src="/js/app.js"></script>
{% endblock %}

Formattery i filtry w Twig

Formattery w Twig pozwalają na przekształcanie danych bezpośrednio w szablonach. Są szczególnie przydatne do formatowania dat, liczb czy operacji na tekście.

Przykłady użycia filtrów

{# Formatowanie dat #}
{{ post.created_at|date("d-m-Y H:i") }}
{{ "now"|date("Y-m-d") }}

{# Formatowanie liczb #}
{{ 1234.567|number_format(2, ',', ' ') }}  {# 1 234,57 #}

{# Operacje na tekście #}
{{ "witaj w aplikacji"|capitalize }}       {# Witaj w aplikacji #}
{{ user.email|lower }}
{{ content|truncate(150) }}
{{ html_content|striptags }}

{# Operacje na tablicach #}
{{ items|length }}
{{ items|first }}
{{ items|last }}
{{ items|join(', ') }}

Kompilacja i cache widoków twig

Twig kompiluje szablony do zoptymalizowanego kodu PHP i przechowuje je w pamięci podręcznej. Dzięki temu renderowanie jest bardzo szybkie - parsowanie odbywa się tylko raz.

Konfiguracja cache

<?php
// config/views.php
return [
    'default' => 'twig',
    'twig' => [
        'paths' => [
            base_path('resources/views/twig'),
        ],
        'cache' => base_path('storage/cache/twig'),
        'auto_reload' => env('APP_ENV') === 'local',
        'debug' => env('APP_DEBUG', false),
    ],
];

Czyszczenie cache

Adapter Twig zawiera metodę clearCache(), która usuwa wszystkie skompilowane widoki. Jest to przydatne podczas deployment lub debugowania.

<?php
public function clearCache(): void
{
    if (!is_dir($this->cacheDir)) {
        return;
    }

    $iterator = new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator(
            $this->cacheDir,
            FilesystemIterator::SKIP_DOTS
        ),
        RecursiveIteratorIterator::CHILD_FIRST
    );

    foreach ($iterator as $file) {
        $file->isDir() ? rmdir($file) : unlink($file);
    }
}

Wzorce projektowe w systemie widoków

Implementacja systemu widoków wykorzystuje sprawdzone wzorce projektowe:

  • Adapter - TwigRendererAdapter adaptuje interfejs Twig\Environment
  • Facade - Klasa View upraszcza interfejs renderowania
  • Factory - ViewManager tworzy odpowiednie adaptery
  • Strategy - Możliwość wyboru różnych rendererów (Twig, Blade, Inertia)
  • Template Method - BaseAdapter definiuje wspólne metody dla adapterów

Testowanie widoków

System widoków jest w pełni testowalny. W kursie znajdziesz testy integracyjne sprawdzające poprawność renderowania szablonów.

<?php
class TwigControllerTest extends TestCase
{
    public function testRenderingTwigView(): void
    {
        $_SERVER['REQUEST_METHOD'] = 'GET';
        //kontroler wywołujący widok z użyciem twig
        $_SERVER['REQUEST_URI'] = '/twig-test';

        $app = Application::getInstance();
        $response = $app->handle($request);

        $this->assertEquals(200, $response->getStatusCode());
        $this->assertStringContainsString('<h1>Test Title</h1>', (string)$response->getBody());

        // Cleanup
        unset($_SERVER['REQUEST_METHOD'], $_SERVER['REQUEST_URI']);
    }
}

Dla kogo jest ten kurs?

  • Programiści PHP chcący zrozumieć, jak działają silniki szablonów
  • Developerzy Laravel/Symfony pragnący poznać mechanizmy pod maską
  • Osoby tworzące własne frameworki i biblioteki
  • Architekci oprogramowania szukający wzorców projektowych w praktyce

🎓 Zbuduj system widoków od zera!

W kursie PHP 8.4 implementujesz kompletny system widoków - od adaptera Twig, przez własny silnik Blade, aż po nowoczesne SPA z Inertia.js i Vue 3. Każdy komponent testowany i zgodny z najlepszymi praktykami.

Kup pełny kurs PHP 8.4 🚀 Pobierz darmowy fragment 📥

Zobacz szczegółowe artykuły o widokach