Ankündigung

Einklappen
Keine Ankündigung bisher.

Templates - Syntax und Eigenschaften

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Templates - Syntax und Eigenschaften

    Nur wenige Themen rund um PHP polarisieren stärker als Templates. Die Meinungen reichen von
    'Brauche ich nicht, PHP reicht'
    bis zu
    'Nimm ein Framework mit einer leistungsfähigen Template Engine'.
    Jede dieser Meinungen hat irgendwo seine Berechtigung.

    Möchte hier mein Templatekonzept (Zielgruppe "Einzelkämpfer" und Plattform
    Embedded Systems) kurz vorstellen und diskutieren.

    - Strenge Trennung von HTML und Programmcode. Keine Logik im Template(Loops etc),
    es wird kein PHP-Code im Template ausgeführt.
    - integriertes Escaping (Kontextwechsel)
    - Filter (raw,url,format,dateformat, eigene können zugefügt werden)
    - Defaultwerte

    Die Templatesyntax ist extrem einfach: Es gibt nur einen Platzhalter vom Typ

    {{placeholder}}

    im Template. Diese Platzhalter können optional durch Filter und
    Defaultwerte ergänzt werden.
    {{placeholder | filter ?? defaultvalue}} oder
    {{placeholder.key | filter ?? defaultvalue}} für das Verarbeiten von Arrays/Objekten.

    Wer mit Twig arbeitet dem sollte das bekannt vorkommen.
    Es ist kein Erlernen einer neuen Templatesprache notwendig. Ebenso ist der "Zusatzaufwand"
    für das Ersetzen der Platzhalter gegenüber der Ladezeit für das Template vernachlässigbar.

    Für das Füllen der Platzhalter stehen assign-Methoden zur Verfügung, welche neben Variablen
    auch Template-Objekte entgegennehmen können. Damit ist ein Verschachteln von Templates möglich.

    Mich interessiert besonders:
    - Was sollte ein Templatesystem unbedingt noch können?
    - Welche Filter sollten fest verfügbar sein, welche nutzt ihr?

    LG jspit

  • #2
    Was ist für dich ein Template? Ausgelagerte HTML Fragmente, ein "Skin" für eine Website, oder was ist deine Definition dafür?
    Keine Logik heißt nur, du verteilst deine Ausgabelogik kreuz und quer. Ein Templatesystem wie twig, blade, smarty, etc kappselen die Ausgabelogik. Dafür brauchst du Schleifen, Kontrollstrukturen und etc.
    Gib mit deinem Templatesystem z.B. eine Tabelle aus, in der du vielleicht noch ein paar Werte anhand von Bedingung formatieren musst und das Problem wird klar.

    Kommentar


    • #3
      Ein Template ist für mich ein Schablone. Im konkreten Fall eine HTML-Vorlage mit Platzhaltern. So in etwa:
      PHP-Code:
      <!DOCTYPE html>
      <
      html lang="de">
        <
      head>
          <
      title>{{title ?? "title"}}</title>
          <
      meta charset="utf-8"/>
        </
      head
        <
      body>
          <
      h3>{{heading}}</h3>
          {{
      content|raw}}
        </
      body>
      </
      html
      Ausgelagerte HTML Fragmente
      trifft es auch ganz gut.
      Für Tabellen usw. habe ich Generatoren wie das hier, da ich diese oft brauche und keine Lust habe mir das jedes mal zusammenzufrickeln. So eine Tabelle füge ich dann über einen normalen Platzhalter in mein HTML ein.
      Da dieses "Templatesystem" sozusagen dumm ist brauche ich selbstredend auch eine Ausgabelogik = PHP.

      Kommentar


      • #4
        jspit Worauf zielt die Frage ab? Willst Du eine Template-Engine entwickeln? Wenn ja - Was wäre der Vorteil gegenüber Twig z. B.?

        - Strenge Trennung von HTML und Programmcode. Keine Logik im Template(Loops etc),
        es wird kein PHP-Code im Template ausgeführt.
        - integriertes Escaping (Kontextwechsel)
        - Filter (raw,url,format,dateformat, eigene können zugefügt werden)
        - Defaultwerte
        Warum keine Loops? Was stattdessen? Bedenke, dass das Ganze immer noch praktikabel sein soll.

        Kommentar


        • #5
          Zitat von jspit Beitrag anzeigen
          Für Tabellen usw. habe ich Generatoren wie das hier, da ich diese oft brauche und keine Lust habe mir das jedes mal zusammenzufrickeln. So eine Tabelle füge ich dann über einen normalen Platzhalter in mein HTML ein.
          Ja, schön und gut, die Tabelle soll aber ein Problem verdeutlichen. Es wird hässlich sobald du Schleifen und ifs brauchst. In der Praxis hast du nicht für alles eine eigenen Komponete welche die Ausgabe kappselt. Insbesondere bei deiner Zielgruppe...

          Vesuch doch mal sowas auszugeben:
          alles über 0 -> grün
          alles unter 0 -> rot
          0 -> grau
          null -> -
          User B Ertrag
          Hans 100
          Peter -
          Maul 0
          Wurf -100
          Entweder hast du dann 5 Templates, oder mischst HTML in dein PHP Code. (oder du glänzt mit CSS... worums aber auch nicht geht!)

          Kommentar


          • #6
            Ich denke, man sollte nicht auf Teufel komm raus auf Template Engines bestehen.

            Gerade bei Kontrollstrukturen.

            Wieso sollte ich erst {{WILDES KONSTRUKT FUER FOR-SCHLEIFE}} ...{{ENDE-WILEDES-KONSTRUKT}} in php umwandeln,
            wenn ich stattdessen <?php for(){ ... }?> verwenden kann.

            Ja, ich habe kein PHP im HTML. Aber muss so etwas auf Teufel komm raus, unbedingt sein?

            Wie ist es umgekehrt?

            HTML-Ausgaben mit PHP erzeugen? Meist geht auch hier der Tenor in "macht man nicht".
            Das würde z. B. für einen Tabellengenerator gelten.

            Kurz gesagt: Mach es einfach so, wie Du es für richtig hälst.

            Und vor allem... bedenke, dass sich einige Template-Engines bereits einen Namen gemacht haben.
            Ob man sie jetzt mag oder nicht. Muss jeder für sich entscheiden.

            Ich bin der Meinung: "Nicht auf Teufel komm raus."

            Erc zeigt dazu ein simples gängiges Beispiel.

            Kommentar


            • #7
              Zitat von hobbyphp Beitrag anzeigen
              Gerade bei Kontrollstrukturen.

              Wieso sollte ich erst {{WILDES KONSTRUKT FUER FOR-SCHLEIFE}} ...{{ENDE-WILEDES-KONSTRUKT}} in php umwandeln,
              wenn ich stattdessen <?php for(){ ... }?> verwenden kann.

              Ja, ich habe kein PHP im HTML. Aber muss so etwas auf Teufel komm raus, unbedingt sein?
              Nicht falsch verstehen. Bei HTML und PHP vermischen hab ich mich dumm ausgedrückt. Was ich meinte ist das vermischen von Geschäftslogik und Ausgabe. Das bei der Ausgabe selbst HTML und PHP vermischt werden ist natürlich kein Problem. Irgendwie muss man es ja ausgeben.
              Ob für die Ausgabe jetzt eine extra Sparach gebraucht wird kann man sich streiten. Brauchen tut man es nicht. Für eine ganz einfaches Template System reicht eine Klasse mit assign() und display(). Die display() Methode included ein PHP Datei, die das Template ist, und exposted die assigned Variablen der PHP Template Datei. Das sorgt für eine Trennung von Geschäftslogik von der Ausgabe. Die verbreiteten Template System machen das selbe in grün, nur das dort ein kompilierungs schritt dazwischen ist, der die Templates nach PHP übersetzt.
              Der Vorteil von einer eigene Sprach ist der syntaktische Zucker. Das Auto-Escaping, angenehmere Syntax, Block Elemente oder Templates mit Vererbung etc. sind schon Dinge die spaß machen.

              Kommentar


              • #8
                Habe eure Botschaft verstanden die dem Sinn nach lautet: Schleifen, Kontrollstrukturen und etc. gehören zu einen Templatesystem unbedingt dazu.

                xm22 : Ich möchte eben keine Engine entwickeln. Meine 'Engine' ist PHP, das reicht mir. Eine weitere Schicht oberhalb von PHP mit eigener Sprache brauche ich nicht.

                Die Realisierung von Loops etc. innerhalb von Templates ist ohne entsprechende Sprachkonstrukte für mich nicht vorstellbar. In der Konsequenz läuft das dann auf eine Engine wie Twig hinaus, die ausgehend von eigenen Sprachkonstrukten nach Compelierung lauffähigen PHP-Code erzeugt.

                Mein 'Templatesystem' soll eben kein lauffähigen Code erzeugen. Die einzige Aufgabe ist es reine HTML-Vorlagen/Bausteine/Fragmente mit Platzhaltern entgegenzunehmen, wahlweise mit Werten oder Bausteinen zu füllen und daraus wieder HTML-Vorlagen bzw. letztlich reines HTML zu erzeugen

                erc :
                In der Praxis hast du nicht für alles eine eigenen Komponete welche die Ausgabe kappselt.
                Richtig. Aber geschätzt für 95% alle Fälle kann ich Generatoren für Tabellen, Formularelemente etc. einsetzen. Für den Rest habe ich keine Hemmungen mit einer speziellen Funktion/Klasse eben genau das gewünschte Resultat zu erzeugen. Nehmen wir dazu mal deine Tabelle aus #5. Die Daten sollen beispielsweise so vorliegen:

                PHP-Code:
                $data = [
                  [
                'User','Ertrag'],
                  [ 
                'Hans',  100],
                  [ 
                'Peter'NULL],
                  [ 
                'Maul',  0],
                  [
                'Wurf', -100]
                ]; 
                Wie würde hierfür das Twig-Template aussehen? Habe kein Zweifel das dies mit Twig möglich ist. Aber hierfür muss doch eine spezielle Lösung eben mit Twig erstellt werden die hier auch nicht mal auf die Schnelle gezeigt werden kann.
                Wer nicht in Twig drin steckt packt das gar nicht. Was die Lesbarkeit mancher Konstrukte aus Twig angeht da habe ich auch Zweifel. Da sind wir bei meiner zweiten Frage bez. Filter/Funktionen.
                Code:
                {{ people|map((last, first) => "#{first} #{last}")|join(', ') }}
                Werden solche Konstrukte in der Praxis benutzt oder soll dies eher zeigen was Twig alles so kann?
                Wie weit ist es sinnvoll die Aufbereitung von Daten in ein Template zu verlagern anstelle das vorab mit PHP zu erledigen?


                Zitat von hobbyphp Beitrag anzeigen
                HTML-Ausgaben mit PHP erzeugen? Meist geht auch hier der Tenor in "macht man nicht".
                Das würde z. B. für einen Tabellengenerator gelten.
                Da hast du wohl
                HTML-Ausgaben mit PHP erzeugen macht man nicht".
                falsch verstanden. Gemeint ist da wohl eine Serie von echo Befehlen a.la. echo "<;h1>;...
                Das macht man wirklich nicht. Die Generatoren welche ich einsetze machen kein echo, sie liefern Strings!

                Kommentar


                • #9
                  Zitat von jspit Beitrag anzeigen
                  Wie würde hierfür das Twig-Template aussehen?
                  Das sieht genauso plump aus wie du das erwartest:

                  PHP-Code:
                  <table>
                      <
                  tr>
                          <
                  th>A</th>
                          <
                  th>B</th>
                          <
                  th>C</th>
                      </
                  tr>
                      {% for 
                  row in data %}
                          <
                  tr>
                              <
                  td>{{row[0]}}</td>
                              <
                  td></td>
                              <
                  td>
                                  {% if 
                  row[1] > %}
                                     <
                  span class="positive">...</span>
                                  {% elseif 
                  row[1] < 0%}
                                     ...
                                  {% elseif ... %}
                                     ...                       
                                  {% endif %}
                              </
                  td>
                          <
                  tr>
                      {% endfor %}
                  </
                  table
                  Zitat von jspit Beitrag anzeigen
                  Wer nicht in Twig drin steckt packt das gar nicht. Was die Lesbarkeit mancher Konstrukte aus Twig angeht da habe ich auch Zweifel. Da sind wir bei meiner zweiten Frage bez. Filter/Funktionen.
                  Code:
                  {{ people|map((last, first) => "#{first} #{last}")|join(', ') }}
                  Werden solche Konstrukte in der Praxis benutzt oder soll dies eher zeigen was Twig alles so kann?
                  Verwendest du tableArray in der Praxis?! Das ist auch nix anderes als wie du mit tableArray machst. Du hast jetzt nicht 1:1 diese Methoden, aber es ist das Selbe in grün.
                  PHP-Code:
                  echo $tableArray->select("CONCAT('#', first, ' ', '#', last")->implode(', '); 
                  PHP-Code:
                  echo $tableArray->map(fn ($row) => "#{$row.first} #{$row.last}")->join(', '); 
                  PHP-Code:
                  echo $tableArray->map(fn ($last$first) => "#{$first} #{$last}")->join(', '); 
                  Das lässt sich natürlich auch mit einer Loop umsetzen. Twig und Smarty bieten dafür sogar noch die Option relativ einfach das erste oder letzte Element in einer Schleife zu erkennen. Letztendlich ist es Geschmackssache. Die Schleife ist der imperative Ansatz, das Verketten geht in Richtung funktional bzw. ist funktional.


                  [QUOTE=jspit;n1584970]Für den Rest habe ich keine Hemmungen mit einer speziellen Funktion/Klasse eben genau das gewünschte Resultat zu erzeugen.[/CODE]

                  Das bezweifel ich grade. Das macht nämlich richtig Arbeit. Nimm eine beliebige Website und überleg wie du das umsetzen würdest. Z.B. das was du grade siehst. Denk dran, dass hier eventuell nicht alles so statisch ist wie es auf den ersten Blick wirkt und achte auf die Feinheiten.

                  Kommentar


                  • #10
                    jspit
                    Ich möchte eben keine Engine entwickeln. Meine 'Engine' ist PHP, das reicht mir. Eine weitere Schicht oberhalb von PHP mit eigener Sprache brauche ich nicht.
                    Mein 'Templatesystem' soll eben kein lauffähigen Code erzeugen.
                    Verstehe ich jetzt nicht. Ob Du es jetzt Template-System oder Template-Engine nennst, macht für mich keinen Unterschied.

                    Kommentar


                    • #11
                      Danke für den twig-Ansatz. Mir helfen konkrete Beispiele ganz gut um eine andere Herangehensweise zu verstehen. So richtig begeistern kann mich das doch immer noch nicht.

                      Zitat von erc Beitrag anzeigen
                      Verwendest du tableArray in der Praxis?!
                      Ja, aber noch nicht so oft. Ich nehme es vorrangig um Konfigurationendaten für Geräte aufzubereiten. Die Masse an Funktionen die dort mittlerweile drinstecken brauche ich nicht wirklich.
                      Ich habe mir Probleme/Aufgaben zu mehrdimensionalen Arrays bei SO rausgesucht und diese dann mit tableArray gelöst. So kamen im Laufe der Zeit so einige Funktionalitäten dazu.
                      Das aber nur am Rande. Mein Tabellengenerator nennt sich einfach nur Table.

                      Zitat von jspit Beitrag anzeigen
                      Für den Rest habe ich keine Hemmungen mit einer speziellen Funktion/Klasse eben genau das gewünschte Resultat zu erzeugen.
                      Zitat von erc Beitrag anzeigen
                      Das bezweifel ich grade. Das macht nämlich richtig Arbeit.
                      Nun das ist relativ und hängt von der Übung ab. Bis ich das obige Beispiel mit Twig umgesetzt habe vergehen vermutlich Tage. Das Beispiel selbst lässt sich aber sogar noch mit einem Tabellengenerator erstellen.
                      Habe das mal gemacht und die dafür mal die Daten etwas erweitert:

                      PHP-Code:
                      $data = [
                        [
                      'user','birth date','points'],
                        [ 
                      'Hans','1995/11/06',  100],
                        [ 
                      'Peter','1993/03/16'NULL],
                        [ 
                      'Allen','1981/02/21',  0],
                        [
                      'Clarke','1982/07/30', -100]
                      ]; 
                      PHP-Code:
                      $html Table::create($data)
                        ->
                      title(Table::FIRSTLINE)
                        ->
                      quoteSpecialChars([truetruefalse])
                        ->
                      format([
                            
                      => "d.m.Y",
                            
                      => function($val){
                              if(
                      $val === null) return " - ";
                              
                      $color '#888';
                              if(
                      $val 0$color '#0A0';
                              elseif(
                      $val 0$color '#A00';
                              return 
                      '<span style="color:'.$color.'">'.$val.'</span>';
                            }])
                        ->
                      getHTML()

                      Inline-Styles sind nicht so toll, CSS-Classen sind besser. Hab ich jetzt gemacht um gleich ein Resultat zu sehen. Das reinfummeln der Tabelle hier hat länger gedauert als das Beispiel zu erstellen..
                      .
                      .
                      user birth date points
                      Hans 06.11.1995 100
                      Peter 16.03.1993 -
                      Allen 21.02.1981 0
                      Clarke 30.07.1982 -100






                      .
                      xm22 : Für mich ist eine Engine immer was gewaltiges. Und was ich da mache steht eben nicht auf einer Stufe mit twig & Co. Werde mal nächstes WE versuchen ob ich twig auf meinen Chips zum laufen bekomme und ein wenig probieren.

                      Kommentar


                      • #12
                        Kannst Du mal etwas Konkretes zeigen, wie das später aussehen soll? Muss ja nicht direkt lauffähig sein. Mir erschließt sich noch nicht so richtig.

                        Kommentar


                        • #13
                          In Twig gibt es viele Möglichkeiten die Tabelle entsprechend zu formatieren. Ich würde hier allerdings CSS Klassen bevorzugen.
                          In Twig gibt es auch die HtmlExtension womit man Klassen je nach Bedingung ausgeben kann. Kennt man vll. sonst auch von Angular.

                          PHP-Code:
                          <td class="{{ html_classes({
                                'text-green': object.value > 0,
                                'text-red': object.value < 0,
                                'text-gray': object.value == 0}) }}"
                          >
                          {{ 
                          object.value|default('-') }}
                          </
                          td
                          html_classes - Documentation - Twig - The flexible, fast, and secure PHP template engine (symfony.com)

                          Kommentar


                          • #14
                            Zitat von xm22 Beitrag anzeigen
                            Kannst Du mal etwas Konkretes zeigen, wie das später aussehen soll? Muss ja nicht direkt lauffähig sein. Mir erschließt sich noch nicht so richtig.
                            Ja, die Probleme zeigen sich immer erst wenn was Konkretes gemacht werden soll.

                            Es soll ein primitives Affenformular erzeugt werden, das bei Eingabe eines Datums und einer Anzahl Tage das Enddatum berechnet.
                            Ich denke mal das könnte so ähnlich auch mit Twig laufen. Ist spekulativ, habe keine Erfahrungen mit Twig.

                            Dafür habe ich 2 Templates erstellt:

                            form_date.tpl.html
                            Code:
                            <!-- Formular  -->
                            <form method="POST">
                              <label for="start">Start date: </label>
                              <input type="date" id="start" name="date" value="{{post.date}}">
                              <label for="days">Anzahl Tage: </label>
                              <input type="text" id="days" name="days" value="{{post.days}}">
                              Enddatum: {{enddate|date('d.m.Y') }}
                              <br><br>
                              <input type="submit" name="submitdate" value="Berechnen">
                            </form>
                            index.tpl.html
                            Code:
                            <!DOCTYPE html>
                            <html lang="de">
                              <head>
                                <meta charset="UTF-8" />
                                <title>{{ title ?? 'demojspittemplate'}}</title>
                              </head>
                              <body>
                                {{formular|raw }}
                              </body>
                            </html>
                            demo_jspittemplate_date.php

                            PHP-Code:
                            <?php
                            error_reporting
                            (-1);  //dev
                            ini_set('display_errors'1);

                            header('Content-Type: text/html; charset=UTF-8');

                            require 
                            __DIR__.'/../class/JspitTemplate.php';

                            //Berechnung
                            $formVal = [
                                
                            'date' => $_POST['date'] ?? date('Y-m-d'),
                                
                            'days' => $_POST['days'] ?? 1
                            ];
                            $endDate date_create($formVal['date'])
                              ->
                            modify($formVal['days'].' Days')
                            ;
                            //Ausgabe
                            JspitTemplate::setTemplatePath(__DIR__.'/../template/');
                            $tplform JspitTemplate::create('form_date.tpl.html')
                              ->
                            assignOnce([
                                  
                            'post' => $formVal,
                                  
                            'enddate' => $endDate
                              
                            ])
                            ;
                            $htmlMain JspitTemplate::create('index.tpl.html')
                              ->
                            assign([
                                  
                            'title' => 'Test Formular',
                                  
                            'formular' => $tplform
                              
                            ])
                              ->
                            getHTML()
                            ;
                            echo 
                            $htmlMain;
                            Einige Bemerkungen zum PHP-Code:
                            • mit assignOnce erfolgen die Ersetzungen sofort, die Platzhalter post und enddate existieren danach nicht mehr.
                            • mit assign werden die Zuweisungen erstmal nur gespeichert. Spätere Zuweisungen auf gleiche Platzhalter überschreiben diese. Die Auflösung erfolgt dann mit getHTML.
                            • mit 'formular' => $tplform wird sozusagen ein Template-Objekt includiert.
                            • Kein Phantasiecode, das funktioniert so schon.
                            • Die Klasse ist vom Typ One-File.





                            Kommentar


                            • #15
                              jspit ah ok - Ich glaube, ich habe es jetzt verstanden. Ob man das jetzt Template Engine oder Template System nennen möchte sei mal dahin gestellt.

                              Allerding finde ich diese Konstruktion aus meiner Erfahrung heraus super umständlich. Und Du hast gegenüber einer reinen Template Engine rein gar nichts gewonnen. Du hast lediglich View-Logik auslagerst. Vielleicht übersehe ich etwas Grundlegendes, aber anhand Deines Beispieles sehe ich keine Vereinfachung oder Einsparung, sondern gesteigerte Komplexität.

                              Kommentar

                              Lädt...
                              X