[PHP] Templateengine

Dieses Thema im Forum "Webentwicklung" wurde erstellt von SeXy, 15. April 2009 .

  1. 15. April 2009
    Templateengine

    Öhm, ich bastel grad ma wieder was in php und wollt mir so ne kleine templateengine bastewln, sodass ich im template nur stehn hab "{content}" und das ersetzt wird durch den content. Ists iwie möglich, dass ich dieses "{content}" dann durch ne Funktion ersetze? Mit str_replace() wirds nämlich nix, was ja auch klar ist.
    Hoffe, dass es da iwie ne Möglichkeit gibt, an der Stelle den content durchn include ersetzen zu lassen.
    Bin auch gern offen für andere Lösungsmöglichkeiten.
     
  2. 15. April 2009
    AW: Templateengine

    hallo,

    hier ist meine Templateklasse... sicher ausbaufähig...

    class_template.php

    PHP:
    <?
    class 
    template
    {
        var 
    $inhalt //Inhalt der gesamten Templatedatei
        
    var  $tmp_file //Templatedatei
        
    var  $mem_loop  '' //Speicher für Loop-Inhalt (Platzhalter + HTML Code)
        
        // __construct wird ausgeführt, wenn die Klasse zum ersten mal aufgerufen wird
        // Sie prüft die Templatedatei auf ihre Existenz.
        // Wenn es sie nicht gibt, wird das Script abgebrochen und eine Fehlermeldung ausgegeben
        
    public function  __construct ( $file $error  '' )
        {
            
    // Überprüft, ob die Datei existiert, wenn ja dann
            
    if( file_exists ( $file ))
            {
                
    $this -> tmp_file  $file ;
                
    $this -> inhalt  file_get_contents ( $file );
            }
            
    // Wenn die Datei nicht exisitert, wird die Fehlermeldung ausgegeben und das Script
            // abgebrochen.
            
    else
            {
                exit(
    "Die Datei <b>" . $file . "</b> konnte nicht gefunden werden!<br>
                      Bitte stellen Sie sicher, dass die Datei exisitert!"
    );
            }
        }
        
        
    // Die Funktion "ersetzen" wird aufgerufen um einzelne Platzhalter zu ersetzen
        
    public function  ersetzen  ( $key $value )
        {
            
    $suche  '/\{' . $key . '\}/' ;
            
    $this -> inhalt  preg_replace ( $suche $value $this -> inhalt 1 );
        }
        
        
    // Die Funktion "getLoop" wird aufgerufen um Loops zu ersetzen,
        // die in der HTML-Datei festgelegt wurden durch {loop:BEZEICHNUNG} ... {loop:end}
        
    public function  getLoop ( $name $anzahl $replacement )
        {
            
    // Speichern der Anzahl an Datensätzen;
            // ermittelt mit z.B. mysql_num_rows(..);
            
    $this -> data_count  $anzahl ;
            
            
    // Suchsyntax für das Durchsuchen der Templatedatei nach Loops
            // eventuelle Verbesserung: 
            // Suchsyntax: '!\{loop:($name)\}(.*)\{loop:end\}!sU'
            
    $regex  '!\{loop:([^\}]+)\}(.*)\{loop:end\}!sU' ;
            
            
    // Sucht nach den Loops in der Templatedatei.
            
    preg_match_all ( $regex $this -> inhalt $match );
            
            if (isset(
    $match [ 1 ]) && isset( $match [ 2 ]))
            {
                
    $total  sizeof ( $match [ 1 ]);
                for (
    $i  0 $i  $total $i ++)
                {
                    
    // Entfernt Whitespaces am Anfang eines Strings
                    // Mehr unter: http://at.php.net/manual/de/function.trim.php
                    
    $nameObj  trim ( $match [ 1 ][ $i ]);
                    
                    
    // Speichert den HTML-Code zwischen {loop..} ... {loop:end}
                    
    $codeSnippet  $match [ 2 ][ $i ];
                    
                    
    // Loop Bauen!
                    
    $this -> buildLoop ( $nameObj $codeSnippet $replacement );
                }
            }
            
            
    // ersetzen des Loops mit den Platzhaltern
            
    $this -> replaceLoop ();
        }
        
        
    // Mit dieser Funktion wird der Loop zusammengebaut
        // Sprich: der HTML-Code wird sooft kopiert, wie es Datensätze gibt
        
    private function  buildLoop ( $name $snippet $replacement )
        {
            foreach (
    $replacement  as  $replacer )
            {
                
    // HTML-Code wird dieser Variabel zugeschrieben
                // und am Ende erneut hinzugefügt
                
    $this -> mem_loop  .=  $snippet ;
                
                
    // $i wird benötigt um zu erkennen wie viele Felder ersetzt werden müssen.
                
    $i  1 ;
                
                do
                {
                    foreach (
    $replacer  as  $key  =>  $value )
                    {
                        
    // Baut die Suchsyntax zusammen
                        // { } sind deliminater und müssen dh deaktiviert werden. 
                        // Andernfalls werden sie bei der Ausgbae auch angezeigt!
                        // preg_quote baut den String zusammen.
                        // ohne preg_quote ist der "." ein spezielles Zeichen....
                        // mehr Infos: http://regexp-evaluator.de/tutorial/metazeichen/#punkt
                        
    $searcher  "~\{"  preg_quote  ( $name  "."  $key '~' ) .  "\}~" ;  
                        
                        
    // Ersetzt die Ergebnisse der Suchsyntax
                        
    $this -> mem_loop  preg_replace ( $searcher $value $this -> mem_loop 1 );
                    }
                    
    $i ++;
                    
                } while (
    $i  !=  count ( $replacer ));
                
            }
        }
        
        
    // Die Funktion replaceLoop wird von der Funktion buildLoop aufgerufen
        // Sie ersetzt den fertigen Loop mit den Platzhaltern in der Templatedatei
        
    private function  replaceLoop ()
        {
            
    // Suchsyntax zusammenbauen
            
    $regex  '!\{loop:([^\}]+)\}(.*)\{loop:end\}!sU' ;
            
            
    // Suchen und ersetzen in der eigentlichen Templatedatei!
            
    $this -> inhalt  preg_replace ( $regex $this -> mem_loop $this -> inhalt 1 );
        }
        
        
    // Gibt den kompletten Inhalt einer Templatedatei zurück und gibt sie nicht aus!
        
    public function  returnTemplate ()
        {
            return 
    $this -> inhalt ;
        }
        
        
    // Die Funktion "ausgabe" gibt das Template aus!
        
    public function  ausgabe ()
        {
            echo 
    $this -> inhalt ;
        }
    }
    ?>
    kurze erklärung:
    faq.php

    PHP:
    <?
    include(
    "class_template.php" );
    1 //Laden der Templatedatei
    $faq_tmp_file  "design/templates/faq.html" ;
    $faq_template  = new  template ( $faq_tmp_file );

    //Abfrage der FAQ aus der Datenbank und anschließend speichern in einen 2. dim. Array
    $sql_a  mysql_query ( "SELECT `Frage` , `Antwort` FROM `faq`" );
    $num_a  mysql_num_rows ( $sql_a );

    $faq  = array();

    while(
    $res_a  mysql_fetch_array ( $sql_a ))
    {
        
    $faq [] = array( "frage"  =>  $res_a [ 0 ],  "antwort"  =>  $res_a [ 1 ]);          
    }

    //einzelne Felder ersetzen
    $faq_template -> ersetzen ( "UEBERSCHRIFT" "hier deine statische Überschrift" );

    //Ersetzen des Loops in der HTML Datei
    $faq_template -> getLoop ( "faq" $num_a $faq );

    //Ausgabe der Templatedatei
    $inhalt  $faq_template -> returnTemplate ();
    ?>
    Glaube erklärt alles was php mäßig angeht...

    hier die templatefile (vorschlag)
    faq.html
    HTML:
    <div id="inhalt3">
    <h1>{UEBERSCHRIFT}</h1>
    {loop:faq} 
     <p>
     <a href="#">{faq.frage}
     <span>{faq.antwort}</span>
     </a>
     </p><br />
    {loop:end}
    </div>
    
    bw wäre eventuell nett ^^

    falls fragen, einfach stellen^^
     
  3. 15. April 2009
    AW: Templateengine

    Ähm verstehe ich richtig du möchtest {content} durch z.b. function xyz() auswechseln?
     
  4. 15. April 2009
    AW: Templateengine

    ich rate dir von einer template-enegine ab, denn für einen anfänger isses fast nicht möglich was performantes zu erstellen.

    warum schreibst du nicht einfach <?php yxz(); ?> an die stelle wo du die funktion haben willst? php ist doch eh schon eine templatesprache

    ansonsten, wenn du wirklich eine template-engine haben willst, schau dir mal [g]php smarty[/g] an oder erstell dir was simples (smarty liefert ja grundlagen). (smarty hat nen haufen overhead -> würde ich an deiner stelle eher meiden)

    das templatesystem des [g]woltlab community framework[/g]s ist recht gut (zum abschaun )
     
  5. 18. April 2009
    AW: Templateengine

    warum soll str_replace() nicht gehen?
    du kannst auch arrays übergeben. das ganze kannste dann auch mit funktionen und so weiter verbessern oder per schleife in mysql abfragen für newsletter o.Ä.

    PHP:
    <?

    $sHTML  "
    <p>News: {NewsHeader}, erstellt um {NewsCreateDate}</p>
    "
    ;

    $aFind  = array
    (
    =>  "{NewsHeader}" ,
    =>  "{NewsCreateDate}"
    );

    $aReplace  = array
    (
    =>  "Template" ,
    =>  "10.10.2009" ;
    );

    echo 
    str_replace ( $aFind $aReplace $sHTML );
    ausgabe ist etwas wie
    Code:
    <p>News: Template, erstellt um 10.10.2009</p>
    
     
  6. 19. April 2009
    AW: Templateengine

    Man kann sehr wohl einen String den man ersetzen will durch eine Funktion behandeln lassen, wenn man statt

    PHP:
    $suche  '/\{' . $key . '\}/' ;
    $this -> inhalt  preg_replace ( $suche $value $this -> inhalt 1 );
    das hier verwendet:

    PHP:
    $suche  '/\{' . $key . '\}/' ;
    $this -> inhalt  preg_replace_callback   $suche   'funktionsname'   $this -> inhalt );
    und dann in der funktion
    PHP:
    function  funktionsname ( $treffer ) {
          return 
    $treffer [ 0 ]. "Hier gebe ich noch was zum treffer dazu" ;
    }

    die treffer auswertet (Beispiel siehe unter http://www.php.net/manual/de/function.preg-replace-callback.php).
     
  7. 19. April 2009
    AW: Templateengine

    nicht gestestet, aber simpler gehts wohl kaum:

    PHP:
    <? php
        
    function  tpl_save_string ( $string )
        {
            static 
    $strings  = array();
            if(
    $string  ===  true )
                return 
    $strings ;
            
            return 
    '@@string_'  . ( array_push ( $strings stripslashes ( $string )) -  1 ) .  '@@' ;
        }
        
        function 
    tpl_no_way ( $func
        {
            exit(
    $func  ' is not allowed!' );
        }
        
        function 
    tpl_exec_tag ( $tag
        {
            
    $tag  preg_replace ( '~("(?:[^\\\\"]+|\\\\.)*"|\''  .
                
    '(?:[^\\\\\']+|\\\\.)*\')~e' 'tpl_save_string(\'\\1\')' $tag );
            
            
    $doNotWant  = array(
                
    'eval' 'exit' 'die' 'shell_exec' 'exec' ,
                
    'popen' 'pcntl_[a-z_0-9]+' 'fsockopen' 'socket_[a-z_0-9]+'
                'system'
    'file_[a-z_0-9]+' 'fopen'
            
    );
            
            foreach(
    $doNotWant  as  $f
                
    $tag  preg_replace ( '~('  $f  ')\s*\(~i' 'tpl_no_way(\'\\1\'' $tag );
            
            foreach(
    tpl_save_string ( true ) as  $i  =>  $str
                
    $tag  str_replace ( '@@string_'  $i  '@@' $str $tag );
            
            if(!eval(
    'return false;'  $tag  ';' ))
                exit(
    'syntax-error in tag: '  $tag );
            
            eval(
    $tag  ';' );
        }
        
        function 
    tpl_display ( $file
        {
            (
    $content  file_get_contents ( $file )) || exit( 'file not readable' );
            
    preg_replace ( '~\{(.*)\}~eU' 'tpl_exec_tag(\'\\1\')' $content ); 
        }
    ?>
    HTML:
    hallo {print "welt"}
     
  8. 20. April 2009
    AW: Templateengine

    PHP:
    $html  str_replace ( '{content}' contentgenerierfunktion (),  $html );
    Wie waers damit?
     
  9. 20. April 2009
    AW: Templateengine

    Ich muss mich Murdoc anschließen! Sich selber eine Template-Engine "zusammenzuschrauben" ist für Anfänger nicht unbedingt ein sinnvolles und einfaches Unterfangen . Außerdem gibt es ja schon einen Haufen fertiger Codes, die du ausprobieren und evaluieren könntest. Wie von Murdoc erwähnt, ist Smarty da sicherlich nicht der schlechteste Einstieg.

    Smarty ist meiner Meinung nach sehr einfach zu benutzen, gerade für Anfänger. Es gibt eine große Community und du findest eigentlich auf alle Fragen die passende Antwort. Der Aufruf von Funktionen innerhalb eines Smarty-Templates mit einem Template-Tag ist von Haus aus implementiert, von daher haste da eigentlich schon das, was du brauchst.

    Den Overhead von Smarty kannst du im weitesten Sinne umgehen, indem du dein System hybride aufbaust, sprich du speicherst/cachest die Ausgabe von Smarty und erstellst meinetwegen statische HTML-Seiten.

    Schau dir bei Gelegenheit mal das Zend Framework an. Es ist objektorientiert, kostenlos und bietet dir die Möglichkeit, alle Komponenten einzeln zu benutzen (z.B. Views (Templates), Datenbankabstraktion, Caching-Mechanismen etc.). Optimal, wenn du nicht jedes mal das Rad neu erfinden willst.

    MFG Chronos
     
  10. Video Script

    Videos zum Themenbereich

    * gefundene Videos auf YouTube, anhand der Überschrift.