PHP Looping Modello Motore Da Zero

Per un progetto che sto cercando di creare un motore di template PHP per le persone con meno esperienza con la lingua può utilizzare i tag {nome} in HTML e il PHP sostituiscilo con una variabile predefinita da un array. Così come il sostegno loop.

Questo è ben oltre le aspettative del progetto, ma come ho già esperienza con PHP ho pensato che sarebbe una bella sfida per tenermi occupato!

Le mie domande principali sono, come faccio a fare il loop parte del parser ed è questo il modo migliore per implementare un tale sistema. Prima ti consiglio un modello esistente sistema, preferirei creare io, per esperienza e perché tutto il nostro progetto deve essere la nostra.

Al momento la base di analisi è fatta con le regex e preg_replace_callback, controlla se $dati[nome] esiste e se non la sostituisce.

Ho provato a fare il loop in una varietà di modi diversi, ma non so se sono sulla buona strada!

Un esempio, se i dati che il motore di analisi è stata data è:

Array
(
    [title] => The Title
    [subtitle] => Subtitle
    [footer] => Foot
    [people] => Array
        (
            [0] => Array
                (
                    [name] => Steve
                    [surname] => Johnson
                )

            [1] => Array
                (
                    [name] => James
                    [surname] => Johnson
                )

            [2] => Array
                (
                    [name] => josh
                    [surname] => Smith
                )

        )

    [page] => Home
)

E la pagina è stata l’analisi è stata qualcosa del tipo:

<html>
<title>{title}</title>
<body>
<h1>{subtitle}</h1>
{LOOP:people}
<b>{name}</b> {surname}<br />
{ENDLOOP:people}
<br /><br />
<i>{footer}</i>
</body>
</html>

Sarebbe produrre qualcosa di simile a:

<html>
<title>The Title</title>
<body>
<h1>Subtitle</h1>
<b>Steve</b> Johnson<br />
<b>James</b> Johnson<br />
<b>Josh</b> Smith<br />
<br /><br />
<i>Foot</i>
</body>
</html>

Il vostro tempo è incredibilmente apprezzato con questo!

Molte grazie,

P. s. Sono completamente d’accordo, perché io sto cercando di creare qualcosa di simile a ciò che già esiste per esperienza, il mio ben formattato e facile da capire la domanda scende votato.

P. p.s mi sembra Che ci sia una massiccia diffusione di opinioni, per questo argomento, si prega di non giù il voto della gente, perché hanno una diversa opinione. Ognuno ha diritto alla propria!

InformationsquelleAutor Pez Cuckow | 2011-02-16



6 Replies
  1. 22

    Un approccio semplice è quello di convertire il template in PHP ed eseguirlo.

    $template = preg_replace('~\{(\w+)\}~', '<?php $this->showVariable(\'$1\'); ?>', $template);
    $template = preg_replace('~\{LOOP:(\w+)\}~', '<?php foreach ($this->data[\'$1\'] as $ELEMENT): $this->wrap($ELEMENT); ?>', $template);
    $template = preg_replace('~\{ENDLOOP:(\w+)\}~', '<?php $this->unwrap(); endforeach; ?>', $template);

    Per esempio, questo converte il tag di template per embedded tag PHP.

    Vedrai che ho fatto riferimenti a $this->showVariable(), $this->data, $this->wrap() e $this->unwrap(). Che è quello che ho intenzione di attuare.

    Il showVariable funzione consente di visualizzare il contenuto della variabile. wrap e unwrap è chiamato a ogni iterazione di fornire chiusura.

    Ecco la mia realizzazione:

    class TemplateEngine {
        function showVariable($name) {
            if (isset($this->data[$name])) {
                echo $this->data[$name];
            } else {
                echo '{' . $name . '}';
            }
        }
        function wrap($element) {
            $this->stack[] = $this->data;
            foreach ($element as $k => $v) {
                $this->data[$k] = $v;
            }
        }
        function unwrap() {
            $this->data = array_pop($this->stack);
        }
        function run() {
            ob_start ();
            eval (func_get_arg(0));
            return ob_get_clean();
        }
        function process($template, $data) {
            $this->data = $data;
            $this->stack = array();
            $template = str_replace('<', '<?php echo \'<\'; ?>', $template);
            $template = preg_replace('~\{(\w+)\}~', '<?php $this->showVariable(\'$1\'); ?>', $template);
            $template = preg_replace('~\{LOOP:(\w+)\}~', '<?php foreach ($this->data[\'$1\'] as $ELEMENT): $this->wrap($ELEMENT); ?>', $template);
            $template = preg_replace('~\{ENDLOOP:(\w+)\}~', '<?php $this->unwrap(); endforeach; ?>', $template);
            $template = '?>' . $template;
            return $this->run($template);
        }
    }

    In wrap() e unwrap() funzione, io uso una pila per tenere traccia dello stato delle variabili. Appunto, wrap($ELEMENT) salva i dati correnti per lo stack, e quindi aggiungere le variabili all’interno di $ELEMENT in corrente di dati, e unwrap() ripristina i dati dallo stack indietro.

    Per maggiore sicurezza, ho aggiunto questo bit extra per sostituire < con PHP echo:

    $template = str_replace('<', '<?php echo \'<\'; ?>', $template);

    Fondamentalmente per evitare qualsiasi tipo di iniezione di codice PHP direttamente,<?, <%, o <script language="php">.

    Utilizzo è qualcosa di simile a questo:

    $engine = new TemplateEngine();
    echo $engine->process($template, $data);

    Questo non è il metodo migliore, ma è un modo potrebbe essere fatto.

    • eval (func_get_arg(0)); OUCH!!
    • Che cosa è con questa riga di codice?
    • la valutazione di visualizzare i dati non può essere buono.
    • In realtà, non credo che eval è male in PHP. Alcuni quadri effettivamente fare eval un sacco.
    • Si può assegnare un nome un po ‘ per favore, e solo perché il suo interno di un quadro non significa la sua perfetta.
    • Come esempio, Yii utilizza eval per eseguire il rendering di alcuni contenuti, come cssClassExpression proprietà e uso require per eseguire il rendering di visualizzare i file, le file sono già in PHP e non ha bisogno di pre-elaborazione. Essere perfetta, l’ho già detto nella risposta che, questo non è il metodo migliore, e, naturalmente, non è perfetto.
    • Un altro buon punto di generare uno script PHP che può essere migliorato per la compilazione in un template PHP poi dopo, che consentirebbe di eliminare l’uso di eval.
    • Alla fine ho usato questo commento e gli altri per costruire una base di analisi del motore di implementare le idee, che è quasi come fasr come alcuni principali di analisi/la memorizzazione nella cache dei motori, ma solo una (relativamente breve) pagina! labs.pegproductions.com/pegParse
    • “includere” è eval(file_get_contents($filename)); 🙂
    • siamo in grado di aggiungere il conteggio di ciclo for ? Grazie

  2. 5

    Ok in primo luogo mi permetta di spiegare qualcosa di dirvi che PHP È UN MODELLO PARSER.

    Facendo quello che facevo, come la creazione di un modello di parser da un modello parser, inutile e, per essere sinceri si ripete me il modello del parser come smarty sono diventati così bene in una inutile operazione.

    Cosa che si dovrebbe fare è la creazione di un modello di aiuto, non un parser come ci ridondanti, in termini di programmazione di un file di modello è indicato come un vista e uno dei motivi per cui è stato dato un nome particolare è che la gente dovrebbe sapere che ci separano dai Modelli, la Logica di Dominio, ecc

    Ciò che si dovrebbe fare è trovare un modo per incorporare tutta l’visualizzare i dati all’interno delle viste stessi.

    Un esempio di questo è l’uso di 2 classi

    • Modello
    • TemplateScope

    La funzionalità del modello di classe è per la Logica di Dominio per impostare i dati per la visualizzazione e la trasformazione.

    Ecco un rapido esempio:

    class Template
    {
        private $_tpl_data = array();
    
        public function __set($key,$data)
        {
            $this->_tpl_data[$key] = $data;
        }
    
        public function display($template,$display = true)
        {
            $Scope = new TemplateScope($template,$this->_tpl_data); //Inject into the view
            if($display === true) 
            {
                $Scope->Display();
                exit;
            }
            return $Scope;
        }
    }

    Questo è extreamly cose di base che si potrebbe estendere, oko, in modo che l’applicazione, Questa è fondamentalmente una classe dove i vostri punti di vista compilare entro l’interprete, questo vi permetterà di avere accesso a metodi all’interno della TemplateScope classe, ma non al di fuori dell’ambito di classe, io.e il nome.

    class TemplateScope
    {
        private $__data = array();
        private $compiled;
        public function __construct($template,$data)
        {
            $this->__data = $data;
            if(file_exists($template))
            {
                ob_start();
                require_once $template;
                $this->compiled = ob_get_contents();
                ob_end_clean();
            }
        }
    
        public function __get($key)
        {
            return isset($this->__data[$key]) ? $this->__data[$key] : null;
        }
    
        public function _Display()
        {
            if($this->compiled !== null)
            {
                 return $this->compiled;
            }
        }
    
        public function bold($string)
        {
            return sprintf("<strong>%s</strong>",$string);
        }
    
        public function _include($file)
        { 
            require_once $file; //:)
        }
    }

    Questa è solo la base e non di lavoro, ma il concetto c’è, Heres un esempio di utilizzo:

    $Template = new Template();
    
    $Template->number = 1;
    $Template->strings = "Hello World";
    $Template->arrays = array(1,2,3,4)
    $Template->resource = mysql_query("SELECT 1");
    $Template->objects = new stdClass();
    $Template->objects->depth - new stdClass();
    
    $Template->display("index.php");

    e all’interno del modello si dovrebbe utilizzare i tradizionali php in questo modo:

    <?php $this->_include("header.php") ?>
    <ul>
        <?php foreach($this->arrays as $a): ?>
            <li><?php echo $this->bold($a) ?></li>
        <?php endforeach; ?>
    </ul>

    Questo permette anche di avere include all’interno di modelli che hanno ancora il $this parola chiave di accesso per includere se stessi, una sorta di ricorsione (ma non è).

    Quindi, non pro-grammaticalmente creare una cache, non c’è nulla nella cache, è necessario utilizzare memcached che memorizza pre compilato codice sorgente all’interno della memoria salto di una grande porzione di compilazione e di interpretare tempo

    • Sembra buono, io sono un gioco. Hai ragione, voglio dire, un modello helper non un modello parser! Grazie,
    • Nessun problema. questa tecnica è molto supportato e sistemi di Zend incorporarlo.
    • Perché il downvote, odio quando le persone fanno, che senza un motivo!!
    • Penso di avere toccato un soggetto con una massiccia gamma di opinioni!
    • Qualsiasi valido ?
  3. 1

    Se io non sono preoccupato per la memorizzazione nella cache o altri argomenti avanzati che avrebbe spinto da un motore di template come smarty, trovo che il PHP è una grande motore di template. Basta impostare le variabili in uno script come normale e quindi includere il file di modello

    $name = 'Eric';
    $locations = array('Germany', 'Panama', 'China');
    
    include('templates/main.template.php');

    main.tempate.php utilizza un alternativa sintassi del tag php che è abbastanza facile per i non php persone da usare, basta dire loro di ignorare tutto avvolto in un tag php 🙂

    <h2>Your name is <?php echo $name; ?></h2>
    <?php if(!empty($locations)): ?>
      <ol>
        <?php foreach($locations as $location): ?>
        <li><?php echo $location; ?></li>
        <?php endforeach; ?>
      </ol>
    <?php endif; ?>
    <p> ... page continues ... </p>
    • Smarty solo la cache del suo disordine.
    • Qui c’è qualcuno che ha scritto un tutorial per quello che stai cercando di fare. Non ho letto abbastanza per commentare la qualità del codice, ma sembra che qualcosa si potrebbe prendere ispirazione da almeno iniziare: codewalkers.com/c/a/Display-Tutorials/…
    • Purtroppo non include passanti, ma sembra interessante! Grazie
    • Cuckow, include loop. Si può fare, mentre, per, …
    • Oh, devo aver completamente perso! /me si Legge su di esso di nuovo!
    • Stavo parlando del link che hai inviato xD
    • oh mio errore. Sì che il link è stato per un bel modello di base del motore. Più come un progetto starter 🙂 È che lungo le linee di quello che stavi cercando?
    • Sembra che è quello che sto cercando, sto lavorando da che e quello che hai postato bancomat.

  4. 1

    Ho avuto un molto semplice rispondere a qualcosa di un po ‘ come questo prima ho iniziato a usare DOMXPath.

    classe è qualcosa di simile a questo (non so se funziona abbastanza come quello che si vuole, ma cibo per la mente come funziona è molto semplice

    <?php
    class template{
    private $template;
    
    function __CONSTRUCT($template)
    {
        //load a template
        $this->template = file_get_contents($template);
    }
    
    function __DESTRUCT()
    {
        //echo it on object destruction
        echo $this->template;
    }
    
    function set($element,$data)
    {
        //replace the element formatted however you like with whatever data
        $this->template = str_replace("[".$element."]",$data,$this->template);
    }
    }
    ?>

    con questa classe, si sarebbe solo creare l’oggetto con qualsiasi template voluto e utilizzare la funzione per inserire tutti i vostri dati.

    semplici passanti dopo che l’oggetto è stato creato probabilmente può raggiungere il tuo obiettivo.

    buona fortuna

    • tenete a mente che ci sono modi MIGLIORI per fare questo (DOMXPath!) ma non suona come avete bisogno di un sacco di muscolo
    • Perché capitalizzare il vostro costruttori ?
    • si downvote me, perché non sfruttare il mio costruttori e distruttori? lol
  5. -4

    Smarty 🙂 …

    php:

    $smarty->assign("people",$peopleArray)

    smarty modello:

    {foreach $people as $person}
    <b>{$person.name}</b> {$person.surname}<br />
    {/foreach}

    E un paio di altre cose da fare, ma è quello che smarty come sarà essenzialmente.

    • nota è possibile assegnare, piastrelle, ecc nello stesso modo. quindi {$titolo} e così via per visualizzarli.
    • “Prima ti consiglio un modello esistente sistema, preferirei creare io, per esperienza e perché tutto il nostro progetto è di essere noi stessi.”
    • beh, questo è esattamente ciò che Smarty e viene utilizzato extensivley da professionisti per esattamente questo tipo di soluzione. Nessun punto di re-inventare la rotellina!
    • Io non sto cercando di essere un professionista, sto solo cercando di creare qualcosa di esperienze e di controllo su quello che fa. Grazie per la tua risposta, in ogni caso, tuttavia.
  6. -11

    Utilizzare Smarty.

    • “Prima ti consiglio un modello esistente sistema, preferirei creare io, per esperienza e perché tutto il nostro progetto è di essere noi stessi.”
    • Questa non è una domanda banale. Meglio chiedere perché le persone consigliamo Smarty! Forse hanno già l’esperienza che si sta cercando.
    • Sono consapevole che alcune persone consigliamo di Smarty, però, come ho detto, io preferisco usare qualcosa che ho creato e capire al 100%, invece di imparare la sintassi per alcuni modelli di motore che io non sono una piena comprensione di come funziona. Ho visto motori molto simile a quello che sto cercando creata da persone che prima con un po ‘ di sforzo

Lascia un commento