Pregunta

En PHP, las declaraciones de cadenas HEREDOC son realmente útiles para generar un bloque de html.Puede hacer que analice variables simplemente anteponiendo $, pero para una sintaxis más complicada (como $var[2][3]), debe poner su expresión entre llaves {}.

En PHP 5, es Es posible realizar llamadas a funciones dentro de {} llaves dentro de una cadena HEREDOC, pero hay que trabajar un poco.El nombre de la función en sí debe almacenarse en una variable y debe llamarla como si fuera una función con nombre dinámico.Por ejemplo:

$fn = 'testfunction';
function testfunction() { return 'ok'; }
$string = <<< heredoc
plain text and now a function: {$fn()}
heredoc;

Como puedes ver, esto es un poco más complicado que simplemente:

$string = <<< heredoc
plain text and now a function: {testfunction()}
heredoc;

Hay otras formas además del primer ejemplo de código, como salir del HEREDOC para llamar a la función o revertir el problema y hacer algo como:

?>
<!-- directly output html and only breaking into php for the function -->
plain text and now a function: <?PHP print testfunction(); ?>

Este último tiene la desventaja de que la salida se coloca directamente en el flujo de salida (a menos que esté usando el almacenamiento en búfer de salida), lo que podría no ser lo que quiero.

Entonces, la esencia de mi pregunta es:¿Existe una forma más elegante de abordar esto?

Editar según las respuestas: Ciertamente parece que algún tipo de motor de plantillas me haría la vida mucho más fácil, pero básicamente requeriría que invierta mi estilo PHP habitual.No es que eso sea malo, pero explica mi inercia.Sin embargo, estoy dispuesto a descubrir formas de hacer la vida más fácil, así que ahora estoy buscando plantillas.

¿Fue útil?

Solución

Personalmente, no usaría HEREDOC en absoluto para esto.Simplemente no es un buen sistema de "construcción de plantillas".Todo tu HTML está encerrado en una cadena que tiene varias desventajas.

  • No hay opción para WYSIWYG
  • No se completa el código para HTML desde IDE
  • Salida (HTML) bloqueada en archivos lógicos
  • Terminas teniendo que usar trucos como el que estás intentando hacer ahora para lograr plantillas más complejas, como bucles.

Obtenga un motor de plantillas básico o simplemente use PHP con inclusiones; es por eso que el lenguaje tiene la <?php y ?> delimitadores.

archivo_plantilla.php

<html>
<head>
  <title><?php echo $page_title; ?></title>
</head>
<body>
  <?php echo getPageContent(); ?>
</body>

index.php

<?php

$page_title = "This is a simple demo";

function getPageContent() {
    return '<p>Hello World!</p>';
}

include('template_file.php');

Otros consejos

Si realmente quieres hacer esto pero un poco más simple que usar una clase, puedes usar:

function fn($data) {
  return $data;
}
$fn = 'fn';

$my_string = <<<EOT
Number of seconds since the Unix Epoch: {$fn(time())}
EOT;

Yo haría lo siguiente:

$string = <<< heredoc
plain text and now a function: %s
heredoc;
$string = sprintf($string, testfunction());

No estoy seguro si considerarías que esto es más elegante...

Pruebe esto (ya sea como una variable global o instanciada cuando la necesite):

<?php
  class Fn {
    public function __call($name, $args) {
      if (function_exists($name)) {
        return call_user_func_array($name, $args);
      }
    }
  }

  $fn = new Fn();
?>

Ahora cualquier llamada a función pasa por el $fn instancia.Entonces la función existente testfunction() se puede llamar en un heredoc con {$fn->testfunction()}

Básicamente, estamos envolviendo todas las funciones en una instancia de clase y usando PHP. __call magic método para asignar el método de clase a la función real que necesita ser llamada.

Llegué un poco tarde, pero lo encontré por casualidad.Para futuros lectores, esto es lo que probablemente haría:

Simplemente usaría un búfer de salida.Básicamente, inicia el almacenamiento en búfer usando ob_start(), luego incluye su "archivo de plantilla" con cualquier función, variable, etc.dentro de él, obtenga el contenido del búfer y escríbalo en una cadena, y luego cierre el búfer.Luego ha utilizado todas las variables que necesita, puede ejecutar cualquier función y aún tiene el resaltado de sintaxis HTML disponible en su IDE.

Esto es lo que quiero decir:

Archivo de plantilla:

<?php echo "plain text and now a function: " . testfunction(); ?>

Guion:

<?php
ob_start();
include "template_file.php";
$output_string = ob_get_contents();
ob_end_clean();
echo $output_string;
?>

Entonces, el script incluye template_file.php en su búfer, ejecutando cualquier función/método y asignando cualquier variable a lo largo del camino.Luego simplemente registra el contenido del búfer en una variable y hace lo que quiera con él.

De esa manera, si no deseas repetirlo en la página justo en ese segundo, no es necesario que lo hagas.Puede realizar un bucle y seguir agregando a la cadena antes de generarla.

Creo que esa es la mejor manera de hacerlo si no quieres utilizar un motor de plantillas.

Para completar, también puede utilizar el !${''} magia negra truco del analizador:

echo <<<EOT
One month ago was ${!${''} = date('Y-m-d H:i:s', strtotime('-1 month'))}.
EOT;

Este fragmento definirá variables con el nombre de sus funciones definidas dentro del alcance del usuario y las vinculará a una cadena que contiene el mismo nombre.Déjame demostrarte.

function add ($int) { return $int + 1; }
$f=get_defined_functions();foreach($f[user]as$v){$$v=$v;}

$string = <<< heredoc
plain text and now a function: {$add(1)}
heredoc;

Ahora funcionará.

Creo que usar heredoc es excelente para generar código HTML.Por ejemplo, lo siguiente me parece casi completamente ilegible.

<html>
<head>
  <title><?php echo $page_title; ?></title>
</head>
<body>
  <?php echo getPageContent(); ?>
</body>

Sin embargo, para lograr la simplicidad, se verá obligado a evaluar las funciones antes de comenzar.No creo que sea una restricción tan terrible, ya que al hacerlo, terminas separando el cálculo de la visualización, lo cual suele ser una buena idea.

Creo que lo siguiente es bastante legible:

$page_content = getPageContent();

print <<<END
<html>
<head>
  <title>$page_title</title>
</head>
<body>
$page_content
</body>
END;

Desafortunadamente, aunque fue una buena sugerencia que hizo en su pregunta vincular la función a una variable, al final, agrega un nivel de complejidad al código, lo cual no vale la pena, y hace que el código sea menos legible, lo cual es la principal ventaja de heredoc.

Encontré una buena solución con la función de envoltura aquí: http://blog.nazdrave.net/?p=626

function heredoc($param) {
    // just return whatever has been passed to us
    return $param;
}

$heredoc = 'heredoc';

$string = <<<HEREDOC
\$heredoc is now a generic function that can be used in all sorts of ways:
Output the result of a function: {$heredoc(date('r'))}
Output the value of a constant: {$heredoc(__FILE__)}
Static methods work just as well: {$heredoc(MyClass::getSomething())}
2 + 2 equals {$heredoc(2+2)}
HEREDOC;

// The same works not only with HEREDOC strings,
// but with double-quoted strings as well:
$string = "{$heredoc(2+2)}";

echaría un vistazo a Sabelotodo como motor de plantillas; no he probado ningún otro, pero me ha funcionado bien.

Si quisieras seguir con tu enfoque actual sin plantillas, ¿qué tiene de malo el almacenamiento en búfer de salida?Le dará mucha más flexibilidad que tener que declarar variables que son los nombres de las funciones que desea llamar.

Un poco tarde pero aún así.¡Esto es posible en heredoc!

Eche un vistazo al manual de php, sección "Sintaxis compleja (rizada)"

Aquí un buen ejemplo usando la propuesta de @CJDennis:

function double($i)
{ return $i*2; }

function triple($i)
{ return $i*3;}

$tab = 'double';
echo "{$tab(5)} is $tab 5<br>";

$tab = 'triple';
echo "{$tab(5)} is $tab 5<br>";

Por ejemplo, un buen uso de la sintaxis HEREDOC es generar formularios enormes con una relación maestro-detalle en una base de datos.Se puede usar la función HEREDOC dentro de un control FOR, agregando un sufijo después de cada nombre de campo.Es una tarea típica del lado del servidor.

te estás olvidando de la función lambda:

$or=function($c,$t,$f){return$c?$t:$f;};
echo <<<TRUEFALSE
    The best color ever is {$or(rand(0,1),'green','black')}
TRUEFALSE;

También puedes usar la función create_function

Los chicos deben tener en cuenta que también funciona con cadenas entre comillas dobles.

http://www.php.net/manual/en/language.types.string.php

Consejo interesante de todos modos.

<div><?=<<<heredoc
Use heredoc and functions in ONE statement.
Show lower case ABC="
heredoc
. strtolower('ABC') . <<<heredoc
".  And that is it!
heredoc
?></div>
<?php
echo <<<ETO
<h1>Hellow ETO</h1>
ETO;

deberías probarlo .después de finalizar la ETO;comando debes darle enter.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top