Mejores prácticas: ¿trabajar con cadenas largas de varias líneas en PHP?

177

Nota: Lo siento si esta es una pregunta extremadamente simple, pero soy algo obsesivo compulsivo con el formato de mi código.

Tengo una clase que tiene una función que devuelve una cadena que formará el texto del cuerpo de un correo electrónico. Quiero que este texto esté formateado para que se vea bien en el correo electrónico, pero también para que no haga que mi código se vea raro. Esto es lo que quiero decir:

class Something
{
    public function getEmailText($vars)
    {
        $text = 'Hello ' . $vars->name . ",

The second line starts two lines below.

I also don't want any spaces before the new line, so it's butted up against the left side of the screen.";
        return $text;
    }
}

pero también podría escribirse como:

public function getEmailText($vars)
{
    $text = "Hello {$vars->name},\n\rThe second line starts two lines below.\n\rI also don't want any spaces before the new line, so it's butted up against the left side of the screen.";
    return $text;
}

¿Pero cuál es el trato con las nuevas líneas y retornos de carro? ¿Cual es la diferencia? ¿Es \n\nel equivalente de \r\ro \n\r? ¿Qué debo usar cuando estoy creando un espacio entre líneas?

Luego está la opción de almacenamiento en búfer de salida y sintaxis heredoc.

¿Cómo manejas el uso de largas cadenas multilínea en tus objetos?

Andrés
fuente
3
Siempre pensé que \ n era nueva línea en Unix \ r es nueva línea en MacOS antes de OS / X, y \ r \ n es nueva línea en Windows. Además, teniendo en cuenta que esta será una cadena que aparece en un mensaje de correo electrónico, querrá asegurarse de que, de cualquier forma que lo haga, se muestre correctamente en la mayoría de los clientes de correo de comando. Sugerencia: Outlook elimina caracteres adicionales de nueva línea en algunos casos, por lo que no siempre obtendrá lo que espera.
Kenny Drobnack el
1
No estoy seguro de si es tan importante, pero originalmente los dos caracteres de 'nueva línea' vinieron cuando tenía una máquina de escribir física que usaba dos caracteres. Uno para volver a colocar el carro en el lado izquierdo de la página (CR - 0xD), y otro que hizo que la página pasara a la siguiente línea (LF - 0xA.) Estoy seguro de que hay personas que saben más sobre esto sin embargo.
mkgrunder

Respuestas:

288

Debe usar HEREDOC u NOWDOC.

$var = "some text";
$text = <<<EOT
  Place your text between the EOT. It's
  the delimiter that ends the text
  of your multiline string.
  $var
EOT;

La diferencia entre Heredoc y Nowdoc es que el código PHP incrustado en un heredoc se ejecuta, mientras que el código PHP en Nowdoc se imprimirá tal cual.

$var = "foo";
$text = <<<'EOT'
  My $var
EOT;

En este caso, $ text tendrá el valor My $var.

Nota: antes del cierre EOT;no debe haber espacios ni pestañas. de lo contrario, recibirá un error

Halfdan
fuente
¿Por qué? Porque todo entre el primer EOT y el segundo se considera una cadena tal como está. Lo que significa que no necesita poner la barra invertida n en todas las cadenas de varias líneas. @Fabian: ¿Cuál es la diferencia entre un HEREDOC y NOWDOC, o son lo mismo?
Kenny Drobnack el
44
@powtac: No, porque tiene que estar en una nueva línea para finalizar un heredoc. Específicamente, tiene que estar EOT;sin espacios antes.
Powerlord
He agregado una explicación para Nowdoc.
halfdan
66
@halfdan, ¿me estoy perdiendo algo? ¿Por qué molestarse con heredocs y nowdocs cuando simplemente podemos escribir la tecla "Enter" y rodear la cadena de varias líneas con comillas como una cadena normal?
Pacerier
3
Simplemente agregue esto a su respuesta: antes del último EOT;no debe haber espacios ni pestañas. de lo contrario, recibirá un error.
Shnd
44

Utilizo un sistema similar a pix0r y creo que eso hace que el código sea bastante legible. A veces, iría tan lejos como para separar los saltos de línea entre comillas dobles y usar comillas simples para el resto de la cadena. De esa manera, se destacan del resto del texto y las variables también se destacan mejor si utiliza la concatenación en lugar de inyectarlas dentro de una cadena entre comillas dobles. Entonces, podría hacer algo como esto con su ejemplo original:

$text = 'Hello ' . $vars->name . ','
      . "\r\n\r\n"
      . 'The second line starts two lines below.'
      . "\r\n\r\n"
      . 'I also don\'t want any spaces before the new line,'
      . ' so it\'s butted up against the left side of the screen.';

return $text;

Con respecto a los saltos de línea, con el correo electrónico siempre debe usar \ r \ n. PHP_EOL es para archivos destinados a ser utilizados en el mismo sistema operativo en el que se ejecuta php.

Cvuorinen
fuente
¿Estableció esa sangría en su IDE (para establecer una cadena multilínea alineada con cada parte)?
Krzysztof Trzos
25

Yo uso plantillas para texto largo:

email-template.txt contiene

hello {name}!
how are you? 

En PHP hago esto:

$email = file_get_contents('email-template.txt');
$email = str_replace('{name},', 'Simon', $email);
Powtac
fuente
interesante ... ¿dónde almacena sus plantillas en la estructura de directorios de una aplicación web?
Andrew
Mi código es solo una demostración. Para una gran aplicación web, puede usar una estructura como / templates / emails /, / templates / userfeedback /. Pero si tiene más cosas, recomendaría un sistema de plantillas completo como SMARTY.
powtac
Dwoo dwoo.org es un sistema de plantillas PHP decente compatible con SMARTY que algunos consideran un buen sucesor (comenzó en PHP5, por lo que no hay equipaje PHP4).
micahwittman
19

Agregar \ny / o \ren el medio de la cadena y tener una línea de código muy larga, como en el segundo ejemplo, no se siente bien: cuando lees el código, no ves el resultado y tienes que desplazarte .

En este tipo de situaciones, siempre uso Heredoc (o Nowdoc, si uso PHP> = 5.3) : fácil de escribir, fácil de leer, sin necesidad de líneas súper largas, ...

Por ejemplo :

$var = 'World';
$str = <<<MARKER
this is a very
long string that
doesn't require
horizontal scrolling, 
and interpolates variables :
Hello, $var!
MARKER;

Solo una cosa: el marcador final (y el ' ;' después de él) debe ser lo único en su línea: ¡sin espacio / tabulación antes o después!

Pascal MARTIN
fuente
12

Claro, podría usar HEREDOC, pero en lo que respecta a la legibilidad del código, en realidad no es mejor que el primer ejemplo, envolviendo la cadena en varias líneas.

Si realmente desea que su cadena de varias líneas se vea bien y fluya bien con su código, le recomiendo concatenar cadenas como tales:

$text = "Hello, {$vars->name},\r\n\r\n"
    . "The second line starts two lines below.\r\n"
    . ".. Third line... etc";

Esto puede ser un poco más lento que HEREDOC o una cadena de varias líneas, pero fluirá bien con la sangría de su código y hará que sea más fácil de leer.

pix0r
fuente
9

Este método me gusta un poco más para Javascript, pero parece que vale la pena incluirlo aquí porque aún no se ha mencionado.

$var = "pizza";

$text = implode(" ", [
  "I love me some",
  "really large",
  $var,
  "pies.",
]);

// "I love me some really large pizza pies."

Para cosas más pequeñas, creo que a menudo es más fácil trabajar con estructuras de matriz en comparación con cadenas concatenadas.

Relacionado: rendimiento implode vs concat

johnny
fuente
1

El que cree que

"abc\n" . "def\n"

La cadena multilínea está mal. Son dos cadenas con operador de concatenación, no una cadena multilínea. Tales cadenas concatenadas no pueden usarse como claves de matrices predefinidas, por ejemplo. Lamentablemente, php no ofrece cadenas multilíneas reales en forma de

"abc\n"
"def\n"

only HEREDOCy NOWDOCsintaxis, que es más adecuada para plantillas, porque dicha sangría de código anidado se rompe por dicha sintaxis.

Dmitriy Sintsov
fuente
1

también puedes usar:

<?php
ob_start();
echo "some text";
echo "\n";

// you can also use: 
?> 
some text can be also written here, or maybe HTML:
<div>whatever<\div>
<?php
echo "you can basically write whatever you want";
// and then: 
$long_text = ob_get_clean();
Alon Gouldman
fuente
0

En lo que respecta a su pregunta sobre líneas nuevas y retornos de carro:

Recomendaría usar la constante global predefinida PHP_EOL ya que resolverá cualquier problema de compatibilidad multiplataforma.

Esta pregunta se ha planteado de antemano en SO y puede obtener más información leyendo "¿ Cuándo uso la constante PHP PHP_EOL? "

Corey Ballou
fuente
1
El comentario a esta respuesta sugiere que debería usar \ r \ n para nuevas líneas en correos electrónicos: stackoverflow.com/questions/128560/…
Andrew
0

¿Pero cuál es el trato con las nuevas líneas y retornos de carro? ¿Cual es la diferencia? ¿Es \ n \ n el equivalente de \ r \ r o \ n \ r? ¿Qué debo usar cuando estoy creando un espacio entre líneas?

Nadie parecía responder realmente esta pregunta, así que aquí estoy.

\r representa 'retorno de carro'

\n representa 'avance de línea'

La razón real de ellos se remonta a las máquinas de escribir. A medida que escribía, el 'carro' se deslizaría lentamente, carácter por carácter, a la derecha de la máquina de escribir. Cuando llegaste al final de la línea, devolverías el carro y luego irías a una nueva línea . Para ir a la nueva línea, debe mover una palanca que alimenta las líneas al escritor de tipos. Por lo tanto, estas acciones, combinadas, se denominaron salto de línea de retorno de carro . Así que literalmente:

Un avance de línea \n, significa pasar a la siguiente línea.

Un retorno de carro \r, significa mover el cursor al comienzo de la línea.

En última instancia, Hello\n\nWorlddebería dar como resultado el siguiente resultado en la pantalla:

Hello

     World

Donde como Hello\r\rWorlddebería resultar en la siguiente salida .

Es solo cuando se combinan los 2 caracteres \r\nque se tiene una comprensión común de la línea conocida. IE Hello\r\nWorlddebería resultar en:

Hello
World

Y, por supuesto, \n\rdaría como resultado la misma salida visual que \r\n.

Originalmente las computadoras tomaron \ry \nliteralmente. Sin embargo, en estos días el soporte para el retorno de carro es escaso. Por lo general, en todos los sistemas puede salirse con la \nsuya. Nunca depende del sistema operativo, pero sí depende de en qué esté viendo la salida.

Aún así, siempre recomendaría usar \r\ndonde sea que puedas.

Sancarn
fuente