[PHP] Template engine (OOP)

Dieses Thema im Forum "Webentwicklung" wurde erstellt von Ragnaroek, 27. August 2008 .

Schlagworte:
Status des Themas:
Es sind keine weiteren Antworten möglich.
  1. 27. August 2008
    Template engine (OOP)

    Hallo,

    ich habe eine template engine gefunden, die eigentlich alles unterstützt, was ich möchte. nur kann sie etwas nicht: die ausgabe von mehreren datensätzen.

    zur engine

    derzeit arbeite ich an meinem eigenen persönlichen blog und möchte dafür gerne diese template engine verwenden.

    bevor ich wie wild los code und am ende nichts rausschaut (wie gestern abend ^^), möchte ich ein paar ideen von euch.

    stellen wir uns folgende problemstellung vor:
    angenommen ich habe mehrere artikel zu einer kategorie (sagen wir Autos).

    dann sollten die ja so aufgelistet werden:
    -Audi - Neuheit A4
    -VW - Golf 6 kommt
    -BMW - M3 noch schneller
    usw....

    man könnte diese werte ja in einen array packen und dann mittels foreach ausgeben. soweit habe ich mir das gedacht... nur bei der umsetzung bin ich kläglich gescheitert... hat nie geklappt...^^

    fällt jmd hier eventuell eine bessere möglichkeit ein?
    ich hätte eine neue funktion geschrieben, in der ich den array fülle (z.b. filltemplate), in der replace mittels foreach dann den array durcharbeite und ersetze und die parse hätte ich eig so belassen.

    bin über jede hilfe und jede idee dankbar!

    gruß
    rag

    ps:
    smarty bringt mir nichts... kann 1. viel zu viel und 2. brauch ich keine template engine die 10 mal so groß wie meine seite ist ^^
     
  2. 27. August 2008
    AW: Template engine (OOP)

    hab dir mal ne kleine template engine geschrieben.
    is ned soo optimal, aber wenn du bisher die oben genannte template-engine verwendet hast, sollte meine für dich optimal sein.

    PHP:
    <? php
        error_reporting
    ( E_ALL | E_STRICT );
        
        class 
    TemplateEngine  {
            private 
                
    $_fetchedTemplatePath $_vars  = array(),
                
    $_base $_comp $_compiler ;
            
            public 
    $force  false ;
            
            

            
    public function  __construct ( $base $comp  null $force  null ) {
                
    $base  str_replace ( '\\' '/' $base );
                if(
    substr ( $base , - 1 ) !=  '/' $base  .=  '/' ;
                if(!
    is_dir ( $base )) {
                    throw new 
    Exception ( 'Templatepfad "'  $base  '" nicht gefunden!' );
                } else {
                    
    $this -> _base  $base ;
                    if(
    is_null ( $comp )) {
                        
    $this -> _comp  str_replace ( '\\' '/' dirName ( __FILE__ )) .  '/comp/' ;
                        if(!
    is_dir ( $this -> _comp ))  mkdir ( $this -> _comp 0640 );
                    } else {
                        
    $this -> _comp  str_replace ( '\\' '/' $comp );
                        if(
    substr ( $this -> _comp , - 1 ) !=  '/' $this -> _comp  .=  '/' ;
                        if(!
    is_dir ( $comp )) {
                            throw new 
    Exception ( 'Templatepfad (compiled) "'  $this -> _comp  '" nicht gefunden!' );
                        }
                    }
                    
                    
    $this -> force  = ( $force  ===  true );
                }
            }
            
            

            
    public function  assign ( $var $value  null ) {
                if(
    is_array ( $var )) {
                    foreach(
    $var  as  $v  =>  $i ) {
                        
    $this -> _vars [ $v ] =  $i ;
                    }
                } else {
                    
    $this -> _vars [ $var ] =  $value ;
                }
            }
            
            

            
    public function  isFetched ( $template , & $path  null ) {
                
    $src  $this -> _getTemplateSource ( $template true );
                
                if(
    $this -> force  ===  true  ||  $src  ==  false
                
    || (! file_exists (( $path  $this -> _comp  $template  '.php' ))))
                    return 
    false ;
                
                
    $sourceMTime  = @ filemtime ( $src );
                
    $compiledMTime  = @ filemtime ( $path );
                if(
    $sourceMTime  <=  $compiledMTime )
                    return 
    true ;
                
                return 
    false ;
            }
            
            

            
    public function  display ( $template ) {            
                if((
    $source  $this -> _getTemplateSource ( $template )) !==  false ) {
                    
    $this -> _render ( $source $template );
                    
    $er  error_reporting ();
                    
    error_reporting ( E_ERROR );
                    include 
    $this -> _fetchedTemplatePath ;
                    
    error_reporting ( $er );
                } else {
                    throw new 
    Exception ( 'Template nicht gefunden!' );
                }
            }
            
            

            
    public function  fetch ( $template ) {
                try {
                    
    ob_start ();
                    
    $this -> display ( $template );
                    
    $result  ob_get_contents ();
                    
    ob_end_clean ();
                    return 
    $result ;
                } catch(
    Exception $e ) {
                    @
    ob_end_clean ();
                    return 
    false ;
                }
            }
            
            

            
    private function  _getTemplateSource ( $template $test  false ) {
                
    //pfad hinzufügen?
                
    if( substr ( $template 0 strlen ( $this -> _base )) !=  $this -> _base )
                    
    $template  $this -> _base  $template ;
                
                
    //template vorhanden?
                
    if(! file_exists ( $template ) || ! is_file ( $template ))
                    return 
    false ;
                
                
    //windows unterscheidet nicht zwischen groß- und kleinschreibung
                
    if( stripos ( PHP_OS 'win' ) && !( baseName ( realPath ( $template )) ==  baseName ( $template )))
                    return 
    false ;
                
                if(
    $test  ===  true )
                    return 
    $template ;
                    
                
    $source  file_get_contents ( $template );
                if(!
    $source
                    return 
    '<!-- empty template -->' //andernfalls würde eine exception geworfen
                    
                
    return  $source ;
            }
            
            

            
    private function  _render ( $source $template ) {
                if(
    $this -> isFetched ( $template $path )) {
                    
    $this -> _fetchedTemplatePath  $path ;
                } else {            
                    
    preg_match_all ( '~\{(.*)\}~U' $source $tags );
                    
    $tags  $tags [ 1 ];
                    if(
    count ( $tags )) {
                        
    $open  = array();
                        foreach(
    $tags  as  $tag ) {
                            
    $find  '{'  $tag  '}' ;
                            if(
    $tag [ 0 ] ==  '/' $com  $tag ;
                            else {
                                if((
    $pos  strpos ( $tag ' ' )) ===  false ) {
                                    
    $com  $tag ;
                                } else {
                                    
    $com  substr ( $tag 0 $pos );
                                    
    $tagWithoutCommand  substr ( $tag $pos  1 strlen ( $tag ));
                                }
                            }
                            
                            switch(
    $com ) {
                                case 
    'foreach' :
                                    
    $tag  'foreach('  $tagWithoutCommand  '):' ;
                                    
    array_push ( $open 'foreach' );
                                    break;
                                case 
    '/foreach' :
                                    list(
    $o ) =  end ( $open );
                                    if(
    $o  !=  'foreach'
                                        throw new 
    Exception ( 'unexpected "/foreach" in '  $template );
                                    
                                    
    array_pop ( $open );
                                    
    $tag  'endforeach;' ;
                                    break;
                                case 
    'if' :
                                    
    $tag  'if('  $tagWithoutCommand  '):' ;
                                    
    array_push ( $open 'if' );
                                    break;
                                case 
    'elseif' :
                                    
    $o  end ( $open );
                                    if(
    $o  !=  'if'  &&  $o  !=  'elseif' )
                                        throw new 
    Exception ( 'unexpected "elseif" in '  $template );
                                    
                                    
    array_pop ( $open );
                                    
    array_push ( $open 'elseif' );
                                    
    $tag  'elseif('  $tagWithoutCommand  '):' ;
                                    break;
                                case 
    'else' :
                                    
    $o  end ( $open );
                                    if(
    $o  !=  'if'  &&  $o  !=  'elseif'  ||  $o  ==  'else' )
                                        throw new 
    Exception ( 'unexpected "/else" in '  $template );
                                    
                                    
    array_push ( $open 'else' );
                                    
    $tag  'else:' ;
                                    break;
                                case 
    '/if' :
                                    
    $o  end ( $open );
                                    if(
    $o  !=  'if'  &&  $o  !=  'elseif'  &&  $o  !=  'else' )
                                        throw new 
    Exception ( 'unexpected "/endif" in '  $template );
                                    
                                    
    array_pop ( $open );
                                    
    $tag  'endif;' ;
                                    break;
                                case 
    'for' :
                                    
    $tag  'for('  $tagWithoutCommand  '):' ;
                                    
    array_push ( $open 'for' );
                                    break;
                                case 
    '/for' :
                                    
    $o  end ( $open );
                                    if(
    $o  !=  'for' )
                                        throw new 
    Exception ( 'unexpected "/for" in '  $template );
                                    
                                    
    array_pop ( $open );
                                    
    $tag  'endfor;' ;
                                    break;
                                case 
    'while' :
                                    
    array_push ( $open 'while' );
                                    
    $tag  'while('  $tagWithoutCommand  '):' ;
                                    break;
                                case 
    '/while' :
                                    
    $o  end ( $open );
                                    if(
    $o  !=  'while'
                                        throw new 
    Exception ( 'unexpected "/while" in '  $template );
                                    
                                    
    array_pop ( $open );
                                    
    $tag  'endwhile;' ;
                                    break;
                                case 
    'break' :
                                case 
    'continue' :
                                    
    $o  end ( $open );
                                    if(!
    in_array ( $o , array( 'for' 'while' 'foreach' )))
                                        throw new 
    Exception ( 'unexpected "'  $com  '" in '  $template );
                                        
                                    
    $tag  .=  ';' ;
                                    break;
                                default: 
                                    if(
    $tag [ 0 ] ==  '@'
                                        
    $tag  'print '  substr ( $tag 1 strlen ( $tag )) .  ';' ;
                                    elseif(
    in_array ( $tag [ 0 ], array( '(' '$' )))
                                        
    $tag  'print '  $tag  ';' ;
                                    else 
    $tag  .=  ';' ;
                            }
                            
                            
    //simple var-access
                            //replace $foo with $this->_vars['foo']
                            
    $tag  preg_replace ( '~\$(\w+)~' '$this->_vars[\'\1\']' $tag );
                            
                            
    //array-dot-access
                            //replace $foo.bar with $foo['bar']
                            
    $tag  preg_replace ( '~\.([^\.\[;]+)~' '[\1]' $tag );
                            
                            
    //fix array-bracket-access
                            //replace [foo] with ['foo']
                            //dont touch [123] or [$foo]
                            
    $tag  preg_replace ( '~\[([^\d\W]+)\]~U' '[\'\1\']' $tag );
                            
                            
    //trim trailing ";"
                            
    $tag  preg_replace ( '~(;+)$~' ';' $tag );
                            
                            
    //replace template-tag with php-tag
                            
    $source  str_replace ( $find '<?php '  $tag  ' ?>' $source );
                        }
                    }
                    
                    
    file_put_contents (( $path  $this -> _comp  $template  '.php' ),  $source );
                    
    $this -> _fetchedTemplatePath  $path ;
                }
            }
        };
    ?>
    verwenden kannst du sie so:
    PHP:
    <? php
        $tpl 
    = new  TemplateEngine ( 'pfad_zu_den_templates' );
        
    $tpl -> assign ( 'variable' 'inhalt' );
        
    $tpl -> assign ( 'query' mysql_query ( 'select 1+1 as erg' ));
        
    $tpl -> display ( 'ein_template.tpl' );
    ?>
    die syntax in den templates is sogut wie die gleiche wie in php:
    (hatte jetzt keinen bock ne eigene syntax zu erfinden )
    Code:
    {$variable} <- sollte "inhalt" ausgeben
    {while $row = mysql_fetch_assoc($query)}
     {@print_r($row, true)} <- sollte "Array ( [erg] => 2 )" ausgeben wenn ich mich ned irre :D
    {/while}
    noch kurz zur syntax:
    {@...} = ausgabe, wird nur benötigt wenn das erste zeichen kein $ oder ( ist.
    {@"test123"} => test123
    {"test123"} => nix, weil kein komando vorhanden ist
    {("test123")} => test123
    {print "test123"} => test123, weil print nicht ausgewertet, sondern so übernommen wird.
    {$foo} => inhalt von $foo
     
  3. 29. August 2008
    AW: Template engine (OOP)

    hallo,

    sorry, dass ich erst jetzt wieder antworte. muss unter der woche immer lange arbeiten und hab dann keine lust mehr, an den pc zu sitzen

    vielen dank für deine engine! werde sie am wocheende gleich mal testen und mir zu gemüte führen

    bw hast du [ehrensache!]!

    thx!

    gruß
    rag
     
  4. 29. August 2008
    AW: Template engine (OOP)

    @Murdoc:
    1. Das hast du doch nicht wirklich "mal-eben-so" gecoded ...
    2. Sehe ich das richtig das man nur einen Ordner angibt und dort alle Templates verwendet werden?
    Wenn ja ist das doch verdammt resourcenintensiv wenn man bei jeder Zuweisung von einer Variable alle Templates bearbeitet (zumal ein Variablenname nicht doppelt innerhalb der Templates vorkommen darf).

    @ Ragnaroek: Wenn dir die Templateengine von oben gefällt und sie für deine Bedürfnisse passt: Dann benutz sie.
    Ansonsten kann ich dir folgende empfehlen (ich benutze sie selber in abgewandelter Form)...
    Die kann genau all das was du willst:
    Ralf Geschke / Blog / Homepage - kuerbis.org und Django, das Python Web-Framework
     
  5. 29. August 2008
    AW: Template engine (OOP)

    Die Class is auch ganz nett: http://lamp.clausvb.de/vlib_mhtml/table_of_content.html
     
  6. 29. August 2008
    AW: Template engine (OOP)

    lol @ Murdoc, da musste ich auch lachen .. "hab dir mal ne kleine template engine geschrieben." top service hier

    sry für offtopic
     
  7. 29. August 2008
    AW: Template engine (OOP)

    Wenn man weiß was man macht, dann geht sowas recht fix, Top arbeit Murdoc
     
  8. 29. August 2008
    AW: Template engine (OOP)

    Naja, "fix" ist relativ zu sehen, für so eine Engine braucht man mindestens 45 Min, ohne weitere tests durchzuführen...
    Und ich denke nicht das er die eben geschrieben hat, nur weil jemand nach soetwas gefragt hat^^...

    Hab noch ein Manko übersehen: Wo liegt der Sinn von Templates (frag ich mich) wenn man wieder PHP Code im Template benutzt?!!?
     
  9. 29. August 2008
    AW: Template engine (OOP)

    Der Sinn ist dann, dass man nur ein Template braucht, für eingeloogt und ausgeloogte Nutzer (als Beispiel).

    Durch eine kleine IF-Bedingung, kannst du halt die "Versteckten" Inhalte anzeigen. Hat schon einige Vorteile. Oder wenn du eine Liste hast, musst du die nicht erst im Code in einen String einfügen, sondern kann das Array an das Template senden, welches es dann auflistet.

    Gibt einige Vorteile. Aber die meisten Skripte nutzen diese nicht, bzw., die meisten Hobby-Skripter kennen diese Vorteile nicht.

    Ich selber .. ja .. hab ne einfache
     
  10. 29. August 2008
    AW: Template engine (OOP)

    Sorry für den zweiten OffTopic Post, aber die Aussage von meinem Vorposter kann ich nicht so stehen lassen.

    @theQuest:
    Hast du schonmal größere Projekte umgesetzt?
    Alleine wenn ich schon lese das man z.B. in einem Template verschiedene Anzeigeelemente (Login/Logout) anzeigen will....
    Das ist doch ein einzig großer Pfusch in dem sich später keiner mehr zurecht findet.

    Ich meine, wenn man das so macht wie du, dann kann man doch gleich alles wieder in PHP schreiben, das ist dann genauso übersichtlich wenn man es strukturiert macht.

    Templates sind dafür da das man den Code vom Design trennen kann.
    Ist doch viel sinnvoller 2 Templates zu machen für "eingeloggt" und "nicht-eingeloggt".

    Ein "IF" ist höchstens für Kleinigkeiten wie "Fett" oder "nicht Fett" gut, aber auch sowas kommt bei mir nicht in die Templates da es nämlich wieder Programmcode ist.

    Also nix für ungut, aber das was du als "Vorteil" bezeichnest, ist absolut KEIN Vorteil!
     
  11. 29. August 2008
    AW: Template engine (OOP)

    Bevor ich ein Template 2 mal erstelle, nur weil ich eine Kleinigkeit ändern muss, bau ich mir da nen bissel Code ein.

    Code:
    <div id="nav">
    <a href="Foo">Link I</a>
    {if $user_logged}
    Hallo {$user_name}
    {else}
    Hallo Gast, anmelden kannst du dich hier ...
    {/endif}
    
    Ich sehe das voll als Vorteil an. Und ja, große Projekte haben mir gezeigt, wer zu viele Templates hat, verzettelt sich schnell. Man will doch nicht für 4 unterschiedliche Benutzergruppen 4 Templates erstellen. Da mach ich mir EIN Template und hab alles im Blick.
     
  12. 30. August 2008
    AW: Template engine (OOP)

    Mein Senf zu dem Thema: PHP Blogger: PHP ist eine Template Engine!
     
  13. 30. August 2008
    AW: Template engine (OOP)

    Hab mir mal alles durchgelesen. Recht habt ihr natürlich schon irgendwie. Das Smarty und Konsorten meist total überladen sind ist richtig. Danke für die Aufklärung.
     
  14. 30. August 2008
    AW: Template engine (OOP)

    doch genau das hab ich^^

    hier ein teil eines templates das ich verwende:
    Code:
    {if $userObj->isLoggedIn()}
     {lang}global.page.welcome{/lang} {@$userObj->getUserName()}
     <p align="center">{@$userObj->getAvatar()}</p>
     <div id="userInformation">
     {foreach from=$userObj->getUserInformation() item=info}
     <h1>{@$info->getTitle()}</h1>
     <p class="userInformationField">{@$info->getContent()}</p>
     {/foreach}
     </div>
    {else} 
     {include file="userLoginForm.tpl"}
    {/if}
    das ganze wird genau einmal (je nach landessprache) via engine gerendert und sieht danach so aus:
    PHP:
    <? php  if( $this -> vars [ 'userObj' ]-> isLoggedIn ()):  ?>
        Willkommen zur&uuml;ck <?php  print  $this -> vars [ 'userObj' ]-> getUserName ();  ?>
        <p align="center"><?php  print  $this -> vars [ 'userObj' ]-> getAvatar ();  ?></p>
        <div id="userInformation">
            <?php  foreach( $this -> vars [ 'userObj' ]-> getUserInformation () as  $this -> vars [ 'info' ]):  ?>
                <h1><?php  print  $this -> vars [ 'info' ]-> getTitle ();  ?></h1>
                <p class="userInformationField"><?php  print  $this -> vars [ 'info' ]-> getContent ();  ?></p>
            <?php  endforeach; unset( $this -> vars [ 'info' ]);  ?>
        </div>
    <?php  else:  ?>
        <?php $this -> display ( 'userLoginForm.tpl' true );  ?>
    <?php 
    endif;  ?>
    da finde ich das template übersichtlicher, vorallem für leihen

    eine template-engine is dann sinnvoll, wenn man apllikationen für andere schreibt.
    ned jeder kann mit nem <?php ... ?> sofort was anfangen und traut sich dann nicht einfach so mal was zu ändern.

    wenn die erstellte applikation für einen selbst ist, dann ist eine template-engine durchaus sinnfrei

    aber denken wir doch mal einen schritt weiter...
    gehen wir mal von einer sehr komplexen app. aus:
    dort soll man ganz einfach via module was erweitern können und benutzer sollen sich ned um den code kümmern müssen.

    da is doch "lad dir dieses plugin für die template-engine runter und fertig"
    besser als "öffne blah.php, such nach mursk(); und ersetze mit kaese();" (<- und in ner komplexen app. schaut sowas noch viel schlimmer aus ).

    vorallem macht es das ganze auch für dich leichter, denn du musst ned stundenlang erklären wie was geht und wo man was ändern muss (was ja alles zeit und geld kostet), sondern du schreibst ein kleines plugin, oder nen hack für ein bestehendes plugin (lässt sich btw sehr gut mit eventhandlern lösen) und die sache is gegessen.

    stichwort: usability.

    man darf dabei auch nicht vergessen welche vorteile so eine template engine hat. man stelle sich mal vor ein benutzer hat in wochenlanger arbeit sein eigenes design entworfen und alles angepasst, möchte jetzt aber eine neue version des php scripts benutzen. tja, ohne template engine müsste das komplette design jetzt erneut in das php-script eingebettet werden, mit einer template-engine hingegen muss er nix dergleichen machen. denn der neue php-code ändert ja nix am template.

    nein du siehst ned richtig^^
    die funktion display() is für das ausgeben der templates zuständig, und nur wenn über diese methode ein template angefordert wird, wird auch ein template gerendert (bzw nicht wenns schon im cache liegt)
     
  15. 30. August 2008
    AW: Template engine (OOP)

    hallo,

    krieg mein xampp gerade nicht zum laufen, dh frag ich einfach mal so ...^^ hoffe geht i.o.

    thx
     
  16. 5. September 2008
    AW: Template engine (OOP)

    ja

    ja, wenn man von "statisch" reden kann. (eher nicht)

    MySQL Datenbankhandbuch: MySQL-Sprachreferenz mit vielen Beispielen: SELECT

    template-syntax >> *.tpl
    php-script >> *.php
     
  17. 8. September 2008
    AW: Template engine (OOP)

    super danke

    funktioniert tadellos =D

    vielen vielen dank!
     
  18. Video Script

    Videos zum Themenbereich

    * gefundene Videos auf YouTube, anhand der Überschrift.