Inno: Template richtig parsen

Hallo,
ich möchte mein eigenes kleines Templatesystem erstellen
und bisher war ich erfolgreich, jedoch stehe ich nun vor einem Problem bei dem ich keine Lösung finde....

Der Code sieht bisher so aus.:
<?php
class Template {
  var $template;

function parse_template($name){
          #$template = file_get_contents('./templates/'.$name.'.php');
   # $filename = './templates/'.$name.'.php';
      ##    $handle = fopen ($filename, "r");
         # $template = fread ($handle, filesize ($filename));
          $template = require_once('./templates/'.$name.'.php');
          $search = array('text' => 'Textdeslanguagefile','Register' => 'Registrieren');
          foreach($search as $key => $value)
          {
                 $template = str_replace('<#lng_'.$key.'#>', $value, $template);
           }
     $this->template = $template;
    # fclose ($handle);
     return $this->template;
  }
}
?>

Die auskommentierten Zeilen waren ältere Versuche von mir.
Das Ausgeben eines Templates und die Funktion str_replace
funktionieren einbandfrei, jedoch kann ich kein PHP mehr im Template
verwenden, um z.B. Variablen oder Ifs zu setzen, die ich in den Templates verwenden möchte.

(Falls jem. eine Lösung kennt Variablenwerte automatisch auszugeben,
wäre es auch sehr hilfreich)

Ich hoffe ihr könnt mir helfen,
Inno

  1. Hallo Inno,

    jedoch kann ich kein PHP mehr im Template verwenden, um z.B. Variablen oder Ifs zu setzen, die ich in den Templates verwenden möchte.

    Das ist richtig. Denn du hast ja einen String vor dir, eingelesen aus dem Dateisystem. Der PHP-Parser wird also gar nicht erst gefragt.
    Wenn du den Code auch ncoh einmal vom Parser durchschauen lassen willst, so ist vermutlich eval() etwas für dich. Sei aber vorsichtig damit und informiere dich gut vor der Verwendung über die Funktion.

    Grüße
      David

    --
    >>Nobody will ever need more than 640k RAM!<<
    1981 Bill Gates
    1. Danke ;-) Hab mir mal das Manual bezüglich eval() angekuckt, jedoch hat sich ein für mich nicht erkennbarer Fehler eingeschlichen...

      PHP wird jetzt vom Template geparst, aber leider nichtmehr str_replaced.

      Code sieht so aus: <?php class Template {   var $template;

      function parse_template($name){           #$template = file_get_contents('./templates/'.$name.'.php');        # $filename = './templates/'.$name.'.php';           ##    $handle = fopen ($filename, "r");           # $template = fread ($handle, filesize ($filename));           $template = require_once('./templates/'.$name.'.php');        eval ("$this->template = "$echo";");           $search = array('text' => 'Textdeslanguagefile','Register' => 'Registrieren');           foreach($search as $key => $value)           {                  $echo = str_replace('<#lng_'.$key.'#>', $value, $template);            }

      # fclose ($handle);      echo $echo;   } } ?>

      1. Hallo Inno,

        $template = require_once('./templates/'.$name.'.php');

        Klassen- und lokale Variablen gleich zu bennen ist doof,

        eval ("$this->template = "$echo";");

        weil man sie schnell verwechseln kann.

        $echo = str_replace('<#lng_'.$key.'#>', $value, $template);

        mehrmals...

        Schau also wann du $this->template und wann $template verwendest bzw verwenden willst.

        Bist du dir auch sicher, dass du die Datei jeweils includen willst? Dann kann es ja auch schon dadurch zu einer ausgabe kommen und ein eval() wäre nicht mehr notwendig..

        Grüße
          David

        --
        >>Nobody will ever need more than 640k RAM!<<
        1981 Bill Gates
        1. Hallo Inno,

          $template = require_once('./templates/'.$name.'.php'); Klassen- und lokale Variablen gleich zu bennen ist doof,

          eval ("$this->template = "$echo";"); weil man sie schnell verwechseln kann.

          $echo = str_replace('<#lng_'.$key.'#>', $value, $template); mehrmals...

          Schau also wann du $this->template und wann $template verwendest bzw verwenden willst.

          Jep, hab die lokale Variable entfernt, da sie keinen Sinn machte.

          Bist du dir auch sicher, dass du die Datei jeweils includen willst? Dann kann es ja auch schon dadurch zu einer ausgabe kommen und ein eval() wäre nicht mehr notwendig..

          Ich habe nur die include Funktion noch darin stehen, da file_get_contents in früheren Fällen Fehler machte bzw. ich glaubte include könnte die Problemlösung sein.

          Hab den Code jetzt bearbeitet: <?php class Template {   var $template;

          function parse_template($name){           #$this->template = file_get_contents('./templates/'.$name.'.php');     $this->template = include('./templates/'.$name.'.php');           $search = array('text' => 'Textdeslanguagefile','Register' => 'Registrieren');           foreach($search as $key => $value)           {                  $echo = str_replace('<#lng_'.$key.'#>', $value, $this->template);      echo 'wird augeführ';            }        eval ("$this->template = "$echo";");     echo $echo;   } } ?>

          Leider kommt folgende Fehlermeldung: Parse error: syntax error, unexpected '<' in /www/htdocs/w008dc4e/web720/system/template.php(13) : eval()'d code on line 2a

          Dazu wird nicht str_replaced.

          Danke, dass du dir die Mühe machst mir zu helfen, Inno

          1. Hallo Inno,

            eval ("$this->template = "$echo";");

            Warum willst du diese einfache Zuweisung evalen? Und wo kommt auf einmal $echo her? Was steht darin?

            Lasse dir immer mal den Inhalt von Variablen ausgeben um zu überprüfen, ob sich darin auch wirklich das versteckt, von dem du annimmst dass es da ist.

            BTW: Du weißt dass str_replace() mit arrays umgehen kann?

            Grüße
              David

            --
            >>Nobody will ever need more than 640k RAM!<<
            1981 Bill Gates
            1. Hallo,
              erstmal danke für deine Antworten,
              was ich nicht für selbstverständlich halte.

              Ich habe nun mein Ergebnis erreicht,
              (hab den Syntax von eval ein wenig fehlinterpretiert),
              jedoch erhalte ich einen für mich unersichtlichen Parse Error
              und zwar:
              Parse error: syntax error, unexpected '<' in /www/htdocs/w008dc4e/web720/system/template.php(8) : eval()'d code on line 2

              Ich verwende überhaupt kein '<' in meiner class und dazu
              wird denke ich mal der Interpreter nicht im Template das '<',
              das für HTML-Elemente benötigt wird meinen.

              Vlt. weißt du ja näheres darüber.

              Mein Code:
              class Template {
                var $template;

              function parse_template($name){
                        $this->template = file_get_contents('./templates/'.$name.'.php');
                   # $this->template = include('./templates/'.$name.'.php');
                     eval ("$this->template = "$this->template";");
                        $search = array('text' => 'Textdeslanguagefile','Register' => 'Registrieren');
                        foreach($search as $key => $value)
                        {
                               $this->template = str_replace('<#lng_'.$key.'#>', $value, $this->template);
                   echo 'wird augeführt';
                         }

              echo $this->template;
                }
              }

              Gruß,
              Inno

              1. Hello,

                Vlt. weißt du ja näheres darüber.

                Über die Verwendung von eval() habe ich erst kürzlich hier 'was geschrieben.
                Der Thread sollte noch vorhanden sein.

                https://forum.selfhtml.org/?t=158831&m=1033009

                Schau bitte mal, ob Du Dich nicht mit dem OP kurzschließen kannst bezüglich Diskusion.

                Harzliche Grüße vom Berg
                http://bergpost.annerschbarrich.de

                Tom

                --
                Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
                Nur selber lernen macht schlau
                Ein Jammer ist auch, dass die Dummen so selbstsicher und die Klugen voller Zweifel sind. Das sollte uns häufiger zweifeln lassen :-)

                1. Argh...
                  tut mir leid, dass ich euch wieder belästigen muss,
                  aber iwie drehe ich mich im kreis:

                  Wenn ich include in der Klasse, wird nicht str_replaced
                  und wenn ich file_get_contents anwende, wird php nichtmehr ausgegeben, obwohl eines eval()s.
                  Hinzu kommt der Parse error:
                  Parse error: syntax error, unexpected '<' in /www/htdocs/w008dc4e/web720/system/template.php(16) : eval()'d code on line 2

                  Ich weiß jetzt überhaupt nichtmehr weiter,
                  daher kann ich nur noch auf euch hoffen:

                  Meine Klasse:
                  <?php
                  class Template {
                    var $template;

                  function parse_template($name){
                            $this->template = file_get_contents('./templates/'.$name.'.php');

                  $search = array('text' => 'Textdeslanguagefile','Register' => 'Registrieren');
                            foreach($search as $key => $value)
                            {
                                   $this->template = str_replace('<#lng_'.$key.'#>', $value, $this->template);
                            }
                      $search = array('<$', '#var>');
                            $replace = array('<?php echo', ';?>');
                            $this->template = str_replace($search, $replace, $this->template);
                         eval ("$this->template = "$this->template";");
                      echo $this->template;
                    }
                  }
                  ?>

                  In der PHP der Aufruf:

                  Templatesystem

                  include('../system/template.php');
                    $template = new Template;

                  $template->parse_template('head');

                  Das Template:
                  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
                  <html xmlns="http://www.w3.org/1999/xhtml">
                  <head>
                      <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
                      <meta name="author" content="InnoVision" />
                   ...... etc. ....
                  </head>
                  <body>
                  <#lng_text#>
                  <?$_SERVER["HTTP_ACCEPT_LANGUAGE"]#var>

                  <?php
                  echo 'zrdz';
                  ?>

                  Wie ihr seht hab ich in die Klasse für mich eine HTML-Klasse für Variablenausgabe erstellt.

                  Ich hoffe ihr könnt mir helfen!

                  1. Hello,

                    tut mir leid, dass ich euch wieder belästigen muss,
                    aber iwie drehe ich mich im kreis:

                    Ja, finde ich auch.

                    Weder include() noch file_get_contents() haben in einer Klassendefinition etwas zu suchen.

                    Der Klasse sollten alle benötigten Ressourcen durch das umgebene Script bereitgestellt werden und es sollten nur Konkurrenzfähige Filefunktionen benutzt werden!

                    Die Überprüfung, ob die passenden "includes()" bereitstehen, kann dann trotzdem in der Klasse erfolgen.

                    Harzliche Grüße vom Berg
                    http://bergpost.annerschbarrich.de

                    Tom

                    --
                    Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
                    Nur selber lernen macht schlau
                    Ein Jammer ist auch, dass die Dummen so selbstsicher und die Klugen voller Zweifel sind. Das sollte uns häufiger zweifeln lassen :-)

                    1. Hallo Tom,

                      Weder include() noch file_get_contents() haben in einer Klassendefinition etwas zu suchen.

                      Naja, file_get_contents() ist IMHO nicht schlimm in diesem Fall. Schließlich wird hier ausschließlich lesend auf die Datei zugegriffen, sodass es keine Probleme mit konkurierendem Zugriff gibt.

                      Grüße
                        David

                      --
                      >>Nobody will ever need more than 640k RAM!<<
                      1981 Bill Gates
                      1. @David:
                        Hm, weißt du vlt. woran das Problem weiterhin liegt?
                        (Hast du vlt. durch Toms Post übersehen);

                        http://forum.de.selfhtml.org/?t=158914&m=1033740

                        Danke

                        1. Ich hab mal das Templatesystem ein wenig anders nach einem Beispiel gestaltet:

                          Funktion.php:
                          <?php
                          function gettemplate($template,$endung="html")
                          {
                             $template = str_replace(""","\"",implode("",file($template.".".$endung)));
                             $search = array('text' => 'Textdeslanguagefile','Register' => 'Registrieren');
                             foreach($search as $key => $value)
                             {
                              $template = str_replace('<#lng_'.$key.'#>', $value, $template);
                             }
                             return $template;
                          }

                          function tploutput($template) {
                                echo $template;
                          }

                          ?>

                          Index.php:
                          <?PHP
                          include("templatefunktion.php");
                          for($inhalt=0;$inhalt<=10;$inhalt++)
                          {
                            eval ("$wiederholung .= "".gettemplate("wiederholung")."";");
                          }
                          eval ("tploutput("".gettemplate("Layout")."");");
                          ?>

                          Es hat alles perfekt funktioniert,
                          jedoch weiß ich nicht wie ich auch noch Arrays neben Variablen
                          im Template verwenden kann.
                          (Wenn ich ein Array hineinsetzte kommt ein Parse error)

                          Kann mir jem. ein Tipp oder sogar den fertigen Codeschnipsel geben?

                          Gruß,
                          Inno

                      2. Hello,

                        Naja, file_get_contents() ist IMHO nicht schlimm in diesem Fall. Schließlich wird hier ausschließlich lesend auf die Datei zugegriffen, sodass es keine Probleme mit konkurierendem Zugriff gibt.

                        Das Lesen mit file_get_contents() ist nicht störsicher. Sollte ein anderer Prozess dieselbe Datei im fraglichen zeitrahmen beschreiben, liest file_get_contents() vermutlich gequirlte Kakke, aber keinesfalls konsistente Daten aus.

                        Deshalb hat es in einer Klassendefinition nichts zu suchen (jedenfalls nicht ohne umfangreiche weitere Maßnahmen)...

                        Harzliche Grüße vom Berg
                        http://bergpost.annerschbarrich.de

                        Tom

                        --
                        Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
                        Nur selber lernen macht schlau
                        Ein Jammer ist auch, dass die Dummen so selbstsicher und die Klugen voller Zweifel sind. Das sollte uns häufiger zweifeln lassen :-)

  2. Ich vergaß..
    ber include() kann ich wiederum nicht str_replacen.

    Da ich gerade sehe, dass der Code nicht so schön durch den Copy & Paste  eingerückt ist, poste ich es für euch nochmal:

    <?php
    class Template {
      var $template;

    function parse_template($name){
              #$template = file_get_contents('./templates/'.$name.'.php');
           # $filename = './templates/'.$name.'.php';
              ##    $handle = fopen ($filename, "r");
              # $template = fread ($handle, filesize ($filename));
              $template = require_once('./templates/'.$name.'.php');
              $search = array('text' => 'Textdeslanguagefile','Register' => 'Registrieren');
              foreach($search as $key => $value)
              {
                     $template = str_replace('<#lng_'.$key.'#>', $value, $template);
               }
         $this->template = $template;
         # fclose ($handle);
         return $this->template;
      }
    }
    ?>

    Ich hoffe mal die Textbox rückt das nicht wieder anders ein.

  3. Hello Inno,

    ich glaube, dass Du auf dem Holzweg bist.
    Du versuchst, den PHP-Parser mittels des PHP-Parsers durch einen selbstentwickelten PHP-Parser zu ersetzen. Das erinnert mich an meine frühen Assembler-Übungen am Commodore PET, wo wir immer versucht haben, die Konsole durch eine "Scherzkonsole" zu ersetzen...

    Ein Template-System ist i.d.R. dafür da, dass man dem User einen gewissen Freiraum einräumen kann, ohne dass er die Kontrolle über das System übernehmen kann. Das erreicht man i.d.R. nur durch Anreihung eigentlich passiver Elemente (also z.B. HTML), die ergänzt werden durch systemkonforme Elemente des passiven Systems, die durch das Template-System dann benutzerbezogen ausgewertet und ersetzt werden können.

    Beispiel:

    <div id="div1">
        <!--{ M-mainmenu ( $pageno )}-->
      </div>

    im HTML-Kontext erscheint ein Kommentar, der von derTemplateengine als Befehl erkannt wird, vom HTML-Parser aber ignoriert wird.

    Hier soll ein Menu dargestellt werden und zwar passend zur angegebenen Seite.
    Die Erscheinungsweise des Menu wird durch ein eigenes Template vereinbart.
    Dieses kann wiederum Template-Befehle enthalten.
    Solange Befehle gefunden werden, werden diese (rekursiv) aufgelöst.

    Es kann aber niemand durch Einschleusen schädlichen Codes die Kontrolle über das System übernehmen.
    An keiner Stelle wird der Code unkontrolliert in den Focus des PHP-Parsers gestellt.
    Es findet also eine strikte Trennung statt
    Das ist dann vergleichbar mit JavaScript im Browser. Auch bei JavaScript können die Randbedingungen sowie Kontrolle über Reessourcen nicht verändert werden, sondern nur die voreingetellten genutzt werden.

    Harzliche Grüße vom Berg
    http://bergpost.annerschbarrich.de

    Tom

    --
    Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
    Nur selber lernen macht schlau
    Ein Jammer ist auch, dass die Dummen so selbstsicher und die Klugen voller Zweifel sind. Das sollte uns häufiger zweifeln lassen :-)

  4. So, ich habe nun auch erreicht, dass meine Arrays geparst werden,
    nur hab ich jetzt einen weiteren Bug bei dem ich mir nichtmehr zu helfen weiß:

    Bei Objektvariablen kann ich keine Arrays ausgeben,
    da Variablen vor ,,[..]´´ schon fertiggeparst werden und es:
    Array[name] ergibt. (Array, da die Variable ja ein Array ist und [name] sollte der Arrayschlüssel sein, den er aber als normalen Text auffast.

    Ich hoffe, ihr wisst wie ich den Parser dazu bringe, nicht vor dem []
    die Variable zu parsen.

    Templatefunktionen:
     function gettemplate($template,$endung="php")
     {
        $template = str_replace(""","\"",implode("",file("./templates/".$template.".".$endung)));
        $search = array('text' => 'Textdeslanguagefile','Register' => 'Registrieren');
        foreach($search as $key => $value)
        {
         $template = str_replace('<#lng_'.$key.'#>', $value, $template);
        }
        return $template;
     }

    function tploutput($template) {
        echo $template;
     }

    index.php:
      include('../system/template.php');
    eval ("tploutput("".gettemplate("head")."");");

    head.php (Template):

    <#lng_text#>
    $member->data[name]

    Fehlermeldung (ist ansich keine, aber nicht das gewünschte ergebnis):

    Array[name]

    Ich hoffe ihr wisst woran es liegt,
    Inno

    1. echo $begrüßung;

      Bei Objektvariablen kann ich keine Arrays ausgeben,
      da Variablen vor ,,[..]´´ schon fertiggeparst werden und es:
      Array[name] ergibt.

      Vielleicht hilft dir die Lektüre des PHP-Handbuch-Kapitels zu Strings, da besonders der Abschnitt Complex (curly) syntax.

      echo "$verabschiedung $name";