PHP - creación de plantillas con etiquetas personalizadas - es este un legítimo uso de eval?

StackOverflow https://stackoverflow.com/questions/3326446

  •  29-09-2020
  •  | 
  •  

Pregunta

Descripción

En torno a finales de 2009, escribí un simple sistema de plantillas para PHP/HTML para ser usado en casa por nuestros diseñadores para folleto-ware tipo de sitios web.El objetivo del sistema es permitir la realización de plantillas en puro HTML a través de etiquetas personalizadas que son procesados por PHP.Por ejemplo, una plantilla de página podría tener este aspecto:

<tt:Page template="templates/main.html">
  <tt:Content name="leftColumn">
    <p> blah blah </p>
    ...
  </tt:Content>
  <tt:Content name="rightColumn">
    <p> blah blah </p>
    ...
  </tt:Content>
</tt:Page>

La plantilla en sí podría ser algo como esto:

<html>
  <head>...</head>
  <body>
    <div style="float:left; width:45%">
      <tt:Container name="leftColumn" />
    </div>
    <div style="width:45%">
      <tt:Container name="rightColumn" />
    </div>
  </body>
</html>

Además de la Página y el Contenido/el Recipiente de las etiquetas, hay un par de etiquetas incluidas en el núcleo, para cosas como el control de flujo, iterar sobre una colección, la salida de los valores dinámicos, etc.El marco está diseñado de una manera muy fácil añadir su propio conjunto de etiquetas registrado bajo otro prefijo y el espacio de nombres.

Etiquetas personalizadas para PHP

¿Cómo podemos analizar estas etiquetas personalizadas?Ya que el son ninguna garantía de que el archivo HTML XML bien formado, soluciones como XSLT/XPATH no ser fiable.En su lugar, se utiliza una expresión regular para buscar etiquetas con marcas de prefijos, y reemplazar aquellos con código PHP.El código PHP es una pila de diseño basado en la...en caso de encontrarse con una etiqueta de apertura, un objeto que representa la etiqueta se crea inserta en la pila, y su "función de inicialización" (si alguno) se ejecuta.Cada vez registrada la etiqueta de cierre es encontrado, el más reciente de objeto se desprendió la pila, y su "función de representación" se ejecuta.

Así que, después de que el marco reemplaza a la de las plantillas de etiquetas con PHP, nuestra página de ejemplo podría ser algo como esto (en realidad es un poco más feo):

<?php $tags->push('tt', 'Page', array('template'=>'templates/main.html')); ?>
  <?php $tags->push('tt', 'Content', array('name'=>'leftColumn')); ?>
    <p> blah blah </p>
    ...
  <?php $tags->pop(); ?>
  <?php $tags->push('tt', 'Content', array('name'=>'rightColumn')); ?>
    <p> blah blah </p>
    ...
  <?php $tags->pop(); ?>
<?php $tags->pop(); ?>

El bueno, el malo, y eval

Ahora, cómo ejecutar nuestro recién generado el código PHP?No puedo pensar en un par de opciones aquí.La más fácil es simplemente eval la cadena, y que funciona bastante bien.Sin embargo, cualquier programador le dirá "eval es malo, no lo uso..." así que la pregunta es, ¿hay algo más apropiado que el de eval que podemos usar aquí?

He considerado el uso de un temporal o en la memoria caché de archivos, el uso de php:// flujos de salida, etc, pero por lo que puedo ver estas no ofrecen ninguna ventaja real con respecto a eval.El almacenamiento en caché podría acelerar las cosas, pero en la práctica todos los sitios que tenemos en esta cosa ya son sorprendentemente rápido, así que no veo necesidad de hacer optimizaciones de velocidad en este punto.

Preguntas

Para cada una de las cosas en esta lista:es una buena idea?Puede usted pensar en una mejor alternativa?

  • la idea en general (etiquetas personalizadas para html / php)
  • la conversión de etiquetas de código de php, en lugar de procesar directamente
  • la pila enfoque basado en
  • el uso de eval (o similar)

Gracias por la lectura y la TIA por cualquier consejo.:)

¿Fue útil?

Solución

Permítanme que abogan por un enfoque diferente.En lugar de generar el código PHP de forma dinámica y, a continuación, tratando de averiguar cómo ejecutar de forma segura, ejecutar directamente como encuentro las etiquetas.Usted puede proceso de todo el bloque de HTML en una sola pasada y manejar cada etiqueta como lo encuentro inmediatamente.

Escribir un bucle que busca las etiquetas.Su estructura básica tendrá este aspecto:

  1. Busque una etiqueta personalizada, que se encuentra en la posición n.
  2. Todo antes de la posición n debe ser simple de HTML, por lo que guardarlo apagado para el procesamiento o la salida de él de inmediato (si no tienen etiquetas en su $tags pila usted probablemente no necesitará guardarlo en cualquier lugar).
  3. Ejecutar el código apropiado para la etiqueta.En lugar de generar el código que llama a $tags->push, solo llame $tags->push directamente.
  4. Volver al paso 1.

Con este enfoque sólo llamar a las funciones de PHP directamente, nunca construir el código PHP sobre la marcha y, a continuación, ejecutarlo más tarde.La necesidad de eval se ha ido.

Básicamente, tendrás que tener dos casos para el paso #3.Cuando se encuentra una etiqueta de apertura que va a hacer de inmediato push.Luego más tarde, cuando usted golpea la etiqueta de cierre que puede hacer un pop y luego manejar la etiqueta de la manera adecuada, ahora que he procesado la totalidad de los contenidos del elemento personalizado.

También es más eficiente para procesar el código HTML de esta manera.Haciendo una búsqueda múltiple y reemplaza en una larga cadena HTML es ineficiente como cada búsqueda y reemplazo es O(n) en la longitud de la cadena.Lo que significa que en repetidas ocasiones el escaneo de la cadena una y otra vez, y cada vez que se realice un reemplazo que han de generar toda una nueva cadenas de longitud similar.Si usted tiene 20KB de HTML, a continuación, cada uno de reemplazo implica la búsqueda a través de 20KB y, a continuación, crear una nueva cadena de 20KB después.

Otros consejos

He publicado otra respuesta porque es radicalmente diferente de la primera, que también podría ser valiosa.

Esencialmente, esta pregunta está preguntando cómo ejecutar código PHP con regex.Puede no parecer obvio, pero esto es lo que el eval es con la intención de llevar a cabo.

Con eso dicho, en lugar de hacer un pase de preg_replace y, a continuación, hacer un eval, sólo podría utilizar PHP preg_replace_callback función a ejecutar un trozo de código cuando se combinan.

Vea aquí cómo funciona: http://us.php.net/manual/en/function.preg-replace-callback.php

Sí, en lugar de eval, usted puede hacer lo que zend y otras grandes marcos, el uso de buffers de salida:

ob_start();
include($template_file); //has some HTML and output generating PHP
$result = ob_get_contents();
ob_end_clean();
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top