Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 11
  1. #1
    Utente di HTML.it L'avatar di JHammer
    Registrato dal
    Sep 2004
    Messaggi
    754

    [Pillola] Studio personale dei template

    Stavo progettando un sistema per gestire i template quando sono arrivato a una soluzione abbastanza originale ma al tempo stesso semplice.
    Non avendo letto molti articoli a proposito voglio discuterla insieme a voi.
    Dunque...sono partito dai template classici...una pagina HTML con dei parametri racchiusi da parentesi {}.
    Per chi non lo sapesse un template si presenta così

    codice:
    <html>
    <head>
    </head>
    <body>
        {testo}
     </body>
    </html>
    Via php posso sostituire a {testo} quello che voglio 'riciclando' lo stesso codice html.

    Però ci sono diversi problemi:
    - se effettuo la sostituzione non posso più effettuarne una seconda
    - se chiamo due parametri con lo stesso nome vengono sostituiti entrambi (pericolo di collisioni)
    - in generale questa soluzione ha la limitazione di non permettere vere e proprie impaginazioni dinamiche!

    Allora mi sono inventato una nuova notazione.
    I parametri tra parentesi li chiamo con fantasia parametri.
    A fianco dei parametri mi sono inventato una seconda entità che chiamo blocco.
    La notazione dei parametri è quella solita: {parametro}
    I blocchi sono invece indicati dalla seguente notazione

    codice:
    ...
    Da osservare che visto che i tag di apertura e chiusura sono dei commenti non generano alcun output e mantiene la compatibilità con il precedente metodo a parametri semplici.

    Le due entità sono perfettamente complementari.
    I parametri possono essere sostituiti mentre i blocchi permettono sia di limitare le sostituzioni al loro contenuto sia di ricopiare se stessi per sostituzioni iterative.

    Penso che con qualche esempio risulti più comprensibile.
    Prima di questo presento il codice.
    E' un pò lunghetto ma l'ho commentato.

    La funzione più interessante è comunque parse_block() che commento brevemente.
    Se non vi interessa potete saltare subito al semplice esempio!

    codice:
    ::parse_block($block, $params, $bremove = true);
    
    - $block rappresenta il nome del blocco
    - $params è un'array associativo : la chiave rappresenta il nome del 
    parametro mentre il valore associato rappresenta il testo
    che vogliamo venga sosituito nelle parentesi {}
    - $bremove è un bool : di default è true cioè il blocco (incluso il tag-commento) 
    scompare dal codice durante la sostituzione; 
    se viene settato a false il blocco viene ricopiato permettendo una nuova sostituzione
    Da notare che se un parametro con lo stesso nome è in un altro blocco o fuori dal blocco specificato non viene modificato.
    Se il blocco contiene un blocco nidificato questo viene ricopiato senza modifiche (sempre che non contenga un parametro con lo stesso nome di quello nel blocco esterno!)

    Qui il codice della classe

    codice:
    
    // Gestisce i templates
    //
    // I templates sono fondamentalmente pagine html con possibilità di sostituire
    // dinamicamente alcune entità.
    // Le entità sono
    // - parametri : {nome_parametro}
    // - blocchi   :
    //
    //        
    //                ... 
    //               blocco
    //                ...
    //        
    //
    // Tutto quello tra beg ed end fa parte del blocco
    // Il blocco può contenere codice HTML, parametri o altri blocchi
    // Essendo racchiuso in un commento html non genera output
    //
    // In entrambi i casi occorre che non ci siano spazi tra il tag di apertura
    // e quello di chiusura( e {...} )
    //  
    
    class zz_template
    {
     
     // carica template da file 
     function loadfile($templatefilename){
        $content=""; 
        if(file_exists($templatefilename)){
        if($hfile = fopen($templatefilename, "r")){
           $content = fread($hfile, filesize($templatefilename));
           fclose($hfile);
        }
      }
      $this->loadstring($content);
     }
     
     // carica template da stringa 
     function loadstring($template){
       $this->template = $template;
     }
     
     // restituisce il codice prodotto dal template 
     function get(){
      return($this->template);
     }
     
    
     // effettua la sostituzione di tutti i parametri (a prescindere dal blocco)
     // sostituisce tutti i parametri con i valori
     // i nomi dei parametri e i valori sono specificati rispettivamente dalle
     // chiavi e dai valori dell'array $params
     // Se bremove è false aggiunge una copia del parametro template 
     // dopo la sostituzione in modo da rendere possibili sostituzioni iterative
     //  
     function parse($params, $bremove = true){
        if($params){
          $keys = array_keys($params);
          for($i=0; $i<count($keys); $i++){ 
            $param_name  = $keys[$i];
            $param_value = $params[$param_name];
            $this->replace($param_name, $param_value, $bremove);
          }
        }
        return($this->template);
     }
    
      
     // come parse ma effettua la sostituzione solo sul blocco block
     // sono sostituiti tutti e solo i parametri che si trovano sia nel blocco che 
     // nelle chiavi di $params 
     // Se bremove è false viene effettuata una copia del template-blocco in modo
     // da rendere possibili sostituzioni iterative
     // Se ci sono parametri con lo stesso nome ma fuori dal blocco o in altri blocchi
     // non vengono sostituiti
     //   
     function parse_block($block, $params, $bremove = true){
        $block_str = $this->getBlock($block);
        $block_content = $this->getBlockContent($block);
        $template = new zz_template();
        $template->loadstring($block_content);
        $template->parse($params, true);
        $text = $template->get().($bremove?"":$block_str);
        $this->template = str_replace($block_str, $text, $this->template);
     }
     
    
     // Rimuove il blocco template block 
     function remove_block($block){ 
        $this->template = str_replace($this->getBlock($block), "", $this->template);
     }
     
     //////////////////////////////////////////////////////////// 
     // metodi privati 
     function replace($param_name, $param_value, $bremove = true){
       $param_tag = "{".$param_name."}";
       $text = $param_value.($bremove?"":$param_tag);
       $this->template = str_replace($param_tag, $text, $this->template);
     }
     
     // prende template (inclusi i tag di beg/end)
     function getBlock($block){
        $startblock_str = "";
        $endblock_str   = "";
       
        if(($s = strpos($this->template, $startblock_str))===false) return "";
        if(($e = strpos($this->template, $endblock_str)) ===false) return "";
        
        return(substr($this->template, $s, $e-$s+strlen($endblock_str)));
     }
     
     // prende solo la parte interna al blocco
     function getBlockContent($block){
        $startblock_str = "";
        $endblock_str   = "";
       
        if(($s = strpos($this->template, $startblock_str))===false) return "";
        if(($e = strpos($this->template, $endblock_str)) ===false) return "";
        
        $offset = strlen($startblock_str);
        $s += $offset; 
        
        return(substr($this->template, $s, $e-$s));
     }
      
     // template e prodotto 
     var $template;
     
    }
    Ok finalmente un esempio semplice

    Ho preparato questo template

    codice:
    <html>
      <head>
      </head>
      <body>
       <ul>
    
       [*]{testo}  
       
    [/list]
      </body>
    </html>
    che ho salvato nel file 'template.html'

    Ora scrivo lo script php

    codice:
    // include il file con la classe (beh...chiamatelo pure come volete)
    require_once("zz_template.php");
    
    // creo una istanza della classe
    $template = new zz_template();
    
    // carico il template dal file html
    $template->loadfile("template.html");
    
    // semplice ciclo da 1 a 10
    for($i=1;$i<=10;$i++){
      // voglio che {testo} sia sostituito con l'indice i
      $param["testo"] = $i;
    
      // effettuo la sostituzione  
      $template->parse_block("blocco", $param, false);
    }
    
    // il blocco non serve più-> rimuoviamolo
    $template->remove_block("blocco");
    
    // stampiamo il risultato
    echo $template->get();
    Il codice sorgente sarà questo

    codice:
    <html>
      <head>
      </head>
      <body>
       <ul>[*]1  [*]2  [*]3  [*]4  [*]5  [*]6  [*]7  [*]8  [*]9  [*]10  [/list]
      </body>
    </html>
    Vista la lunghezza della pillola non mi sembrava il caso di presentare un esempio più complesso...considerate comunque che ogni blocco potrebbe contenere frammenti HTML molto più complessi, più parametri,...
    Addirittura potremmo avere blocchi nidificati i quali possono venire parsati in fasi diverse.

    Piaciuta la pillola ?


  2. #2
    io ti do un up nn l'ho letta mi son bloccato quando hai iniziato con le classi
    cmq sembra molto interessante

  3. #3
    Utente di HTML.it L'avatar di JHammer
    Registrato dal
    Sep 2004
    Messaggi
    754
    allora salta al fondo con l'esempio...dai...sono 4,5 funzioni per fare tutto...

  4. #4
    Utente di HTML.it
    Registrato dal
    May 2001
    Messaggi
    185

    interessante

    per il mio sito sto cercando di vedere se un motore di template fosse utile, é spiegato bene come fare un template, anche se fatico a metterlo in parallelo con quest'articolo:

    http://pro.html.it/articoli/id_582/idcat_31/pro.html

  5. #5
    Utente di HTML.it
    Registrato dal
    May 2001
    Messaggi
    185
    inoltre ho visto che il template lo prendi da un file html, ma potresti prenderlo anche da un file php?
    perche per esempio nel template potrei voler inserire un modulo per eseguire il login, e quindi ci vorrebbero inclusioni di tipo php.

    e poi il template, vale la pena prenderlo da un file o una soluzione sarebbe salvarlo in un db, oppure la lettura dal db sarebbe troppo onerosa?

  6. #6
    Utente di HTML.it
    Registrato dal
    Aug 2002
    Messaggi
    311

    Re: [Pillola] Studio personale dei template

    Originariamente inviato da JHammer
    Stavo progettando un sistema per gestire i template quando sono arrivato a una soluzione abbastanza originale ma al tempo stesso semplice.
    ...
    Ciao...
    faccio fare un up a questa discussione perchè mi sembra davvero positiva....
    dunque è da un pò di giorni che sto tentando anch'io di fare un Template Engine personale e soprattutto semplice. Tutto va più o meno senza problemi... adesso però mi sono fermato su un problema che deriva più che altro da una questione logica:
    Come hai fatto tu, JHammer, a far parsare al motore anche strutture annidate?
    ad esempio:
    codice:
    <[foreach]>
    <div>
    
     <div id="cat_<[nncategoria]>"><[nome_categoria]></div>
    <[foreach]>
     <div id="scat_<[nnsottocategoria]>">
      <a><[nome_sottocategoria]></a>
      <div><[descrizione_sottocategoria]></div>
     </div>
    <[/foreach]>
    
    </div>
    
    
    <[/foreach]>
    
    
    <[foreach]>
     <div id="temp_<[nntemp]>"><[temp]></div>
    <[/foreach]>
    Non riesco a far ripetere il foreach interno!!! Se ci riesco poi non mi "parsa" bene il secondo FOREACH esterno.
    Tu come hai fatto?

    Grazie.

  7. #7
    Utente di HTML.it
    Registrato dal
    Aug 2002
    Messaggi
    311
    uhm...

  8. #8
    per le strutture annidate consiglio di sfruttare array multidimensionali: ho visto che quando parso XML sono molto utili...

  9. #9
    Utente di HTML.it
    Registrato dal
    Aug 2002
    Messaggi
    311
    Originariamente inviato da andrea.paiola
    per le strutture annidate consiglio di sfruttare array multidimensionali: ho visto che quando parso XML sono molto utili...
    Ciao...
    non so più dove sbattere la testa... sto facendo righe e righe di codice senza più sinceramente cercare un senso vero e proprio. Voi partendo da queste 4 righe funzionanti... come fareste a trovare e collezionare tutti i <[foreach]>?
    forse sbaglio semplicemente l'Espressione Regolare... bo non so!
    codice:
    ...
    ...
        $fp = fopen ($filename, "r");
        $this->buffer = fread($fp, filesize($filename));         
        fclose($fp);
        
    	$i=0;
    	while($result = ereg("<\[foreach\]>(.+)<\[\/foreach\]>",$this->buffer,$token)){
    	 $this->foreacharr[] = $token[1];
    	 $this->buffer = ereg_replace("<\[foreach\]>.+<\[\/foreach\]>","<[foreach$i]>",$this->buffer);
    	 $i++;
        }
    ...
    ...
    Adesso vado a nanna che a furia di provare e risprovare ho fatto le 3 del mattino...

    Please help me.

    Thanks.

    P.S.:ragazzi non voglio la pappa pronta, ma se almeno mi date una dritta iniziale posso poi continuare io... a me non sono rimaste più idee (funzioni ricorsive, cicli, ho provato di tutto... )

  10. #10
    Utente di HTML.it
    Registrato dal
    Aug 2002
    Messaggi
    311
    UHM... HELP?!?


Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.