Wirklich einfache PHP Templates - So leicht trennst du dein HTML vom Code mit eigenen Views

Egal, ob du ein Wordpress-Plugin erstellst, bestehenden Code erweiterst oder einfach nur ein kleines PHP-Projekt umsetzt, welches ohne Framework auskommt: Du solltest dabei generell Spaghetti-Code vermeiden.

Ich zeige dir hier eine sehr einfache Möglichkeit, wie du in PHP deine Logik vom HTML trennen kannst. Und das Beste: Ich verzichte auf jegliche Art von Templating-Sprachen wie Twig oder Smarty. Auch ansonsten gibt es keine Abhängigkeiten. Bereit? Los gehts!

Ein typisches Beispiel

Schau dir dieses typische Kontaktformular-Beispiel an. Es verwendet verschiedene Techniken, um HTML zu generieren:

<?PHP
    
    // Hinweis: Dieser Code ist stark vereinfacht. Er dient lediglich als Beispiel. Verwende ihn nicht in Produktion, da grundlegende Sicherheitsmechanismen fehlen.
    
    if(isset($_POST['send'])){
        
        $to = "webmaster@example.com";
        $from   = $_POST['email'];
        $subject    = "Kontaktnachricht von der Website";
        $reply_to  = $_POST['email'];
        
        $header  = "MIME-Version: 1.0\r\n";
        $header .= "Content-type: text/html; charset=utf-8\r\n";
        $header .= "From: $from\r\n";
        $header .= "Reply-To: $reply_to\r\n";
        $header .= "X-Mailer: PHP ". phpversion();
        
        $html = 'Hallo. Es gibt eine neue Kontakanfrage von der Website.<br><br>';
        $html.= 'Betreff: '.$_POST['subject'].'<br><br>';
        $html.= 'Nachricht: '.$_POST['message'].'<br><br>';
        $html.= 'E-Mail: '.$_POST['email'].'<br><br>';
         
        mail ( $to, $subject, $html, $header);
        
        echo 'Vielen Dank für deine Nachricht! Ich kümmere mich so schnell wie möglich um deine Anfrage!<br><br>';
        
        ?>
  
        <b>Betreff:</b> <?=$_POST['subject'] ?><br><br>';
        <b>Nachricht:</b> <?=$_POST['message'] ?><br><br>';
        
        <?PHP

    }else{
    
    ?>
    
        Hey! Hier kannst du mir eine Kontakanfrage senden!
    
        <form method="post">
            <input required type="text" name="subject"><br>
            <textarea required name="message"><textarea><br>
            <input required type="email" name="email"><br>
            <input type="hidden" name="send">
            <input type="submit">
        </form>
    
    <?PHP
    
    }
    
?>

Dieser Code generiert ein Kontaktformular. Sobald es gesendet ist, wird eine HTML-Email und eine Erfolgs-Meldung generiert. Dieser Code erzeugt also an drei verschiedenen Stellen HTML.

Ein alternativer Ansatz mit Views

Mit steigender Komplexität und mit steigender Anzahl an Feldern im Formular wird der Code jedoch unübersichtlicher. Wie können wir jedoch einfach und elegant das HTML von der restlichen Logik trennen?

Die Lösung heißt Views bzw. auch Templates! Schau dir den folgenden Code an. Dieser macht das gleiche, wie das Beispiel oben:

<?PHP
    
    include('View.php');
    
    // Hinweis: Dieser Code ist stark vereinfacht. Er dient lediglich als Beispiel. Verwende ihn nicht in Produktion, da grundlegende Sicherheitsmechanismen fehlen.
    
    if(isset($_POST['send'])){
        
        $to = "webmaster@example.com";
        $from   = $_POST['email'];
        $subject    = "Kontaktnachricht von der Website";
        $reply_to  = $_POST['email'];
        
        $header  = "MIME-Version: 1.0\r\n";
        $header .= "Content-type: text/html; charset=utf-8\r\n";
        $header .= "From: $from\r\n";
        $header .= "Reply-To: $reply_to\r\n";
        $header .= "X-Mailer: PHP ". phpversion();
        
        $html = View::render('mail_message',[
            'subject' => $_POST['subject'],
            'message' => $_POST['message'],
            'email' => $_POST['email']
        ]);
         
        mail ( $to, $subject, $html, $header);
        
        echo View::render('form_success',[
            'subject' => $_POST['subject'],
            'message' => $_POST['message']
        ]);

    }else{
    
        echo View::render('form');
    
    }
    
?>

Hier werden einfach alle erforderlichen Parameter an eine View-Klasse übergeben, welche dann für die Generierung des HTMLs verantwortlich ist.

Wo kommt das HTML jetzt her?

Werfen wir zunächst einen Blick auf die sehr übersichtliche View-Klasse (View.php):

<?PHP

class View {

  public static function render ($v0738238615_name, $arguments = []) {
  	ob_start();
  	if(is_array($arguments)){
  		extract($arguments);
  	}

  	include(__DIR__.'/views/'.$v0738238615_name.'.php');
  	return ob_get_clean();
  }

}

Die Render-Methode erwartet zwei Argumente. Zum einen den Namen des Views und zum anderen ein Array mit Parametern, welches an das View übergeben wird.

Die Funktion "extract" extrahiert dabei die Parameter aus dem Array, sodass diese direkt im View als Variablen zur Verfügung stehen.

Danach wird das View einfach inkludiert. Views sind hier schlichte PHP-Dateien, die alle im Ordner "views" abgelegt sind. In Ihnen wird das HTML definiert.

Die kryptische Variable "$v0738238615_name" hat diesen Namen nur, damit es unwahrscheinlich wird, dass "extract()" diesen Namen mit Parametern aus dem zweiten Argument überschreibt. Würde die Variable einfach $name lauten, könnte der Parameter "name" nicht mehr in Views benutzt werden.

Die Funktionen "ob_start" und "ob_get_clean" sorgen dann einfach dafür, dass der komplette Output aus dem View sauber zurückgegeben werden kann.

Jetzt fehlen noch die Views

Im Ordner "views" müssen also drei Dateien vorhanden sein:

views/form.php

Hey! Hier kannst du mir eine Kontakanfrage senden!
    
<form method="post">
    <input required type="text" name="subject"><br>
    <textarea required name="message"><textarea><br>
    <input required type="email" name="email"><br>
    <input type="hidden" name="send">
    <input type="submit">
</form>

views/form_success.php

Vielen Dank für deine Nachricht! Ich kümmere mich so schnell wie möglich um deine Anfrage!<br><br>

<b>Betreff:</b> <?=$subject ?><br><br>';
<b>Nachricht:</b> <?=$message ?><br><br>';

views/mail_message.php

Hallo. Es gibt eine neue Kontakanfrage von der Website.<br><br>
Betreff: <?=$subject ?> <br><br>
Nachricht: <?=$message ?> <br><br>
E-Mail: <?=$email ?><br><br>

Auch komplexe Templates sind möglich

Du kannst mit dieser Technik auch komplexere Templates erstellen. Übergib als Parameter zum Beipiel ein Array, um dann im View mit "foreach()" eine Liste zu rendern:

<?PHP
$list = ['one', 'two', 'three'];
echo View::render('list', ['items' => $list]);
?>

list.php:

<ul>
    <?PHP
    foreach($items as $item){
    ?>
        <li><?=$item ?></li>
    <?PHP
    }
    ?>
</ul>

Oder übergib einfache Parameter mit den Werten "true" oder "false", die du im Template mit "if" prüfst, um dein Template in einen alternativen Render-Zustand zu versetzen.

<?PHP
$list = ['one', 'two', 'three'];
echo View::render('list', ['items' => $list, 'render_as_list' => true]);
?>

list.php:

<?PHP
if($render_as_list){
    ?>
    <ul>
        <?PHP
        foreach($items as $item){
        ?>
        <li><?=$item ?></li>
        <?PHP
        }
        ?>
   </ul>
   <?PHP
} else {
    echo implode(', ', $items);
}
?>

Du kannst die Methode sogar direkt in deinen Views nutzen, um kleinere Untertemplates einzubinden:

list.php:

<ul>
    <?PHP
    foreach($items as $item){
        echo View::render('list_item', ['item' => $item]);
    }
    ?>
</ul>

list_item.php:

<li><?=$item ?></li>

Auch kannst du deine Views mit weiteren Ordnern unterteilen, um aufgeräumter zu sein:

echo View::render('emails/confirmation_email');
echo View::render('emails/contact_email');
echo View::render('site/header/logo');
echo View::render('site/header/menu');
echo View::render('site/footer');

All das geht mit dieser einfachen Technik.

War das einfach oder war das einfach?

So leicht trennst du mit einer simplen Render-Methode dein ganzes HTML vom Code. Dein Code wird dadurch nicht nur übersichtlicher, sondern auch leichter austauschbar. So kannst du zum Beispiel schnell alternative Layouts für dein Formular oder die E-Mail anlegen.

Beitragsbild: [lmonk72](https://pixabay.com/de/photos/code-codierung-web-entwicklung-944499/)