Meilleures pratiques: travailler avec de longues chaînes multilignes en PHP?

178

Remarque: je suis désolé si c'est une question extrêmement simple mais je suis quelque peu obsessionnel compulsif sur le formatage de mon code.

J'ai une classe qui a une fonction qui renvoie une chaîne qui composera le corps du texte d'un e-mail. Je veux que ce texte soit formaté pour qu'il apparaisse bien dans l'e-mail, mais aussi pour que mon code ne paraisse pas génial. Voici ce que je veux dire:

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;
    }
}

mais il pourrait aussi s'écrire:

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;
}

mais quel est le problème avec les nouvelles lignes et les retours chariot? Quelle est la différence? Est-ce \n\nl'équivalent de \r\rou \n\r? Lequel dois-je utiliser lorsque je crée un espace entre les lignes?

Ensuite, il y a l'option de mise en mémoire tampon de sortie et la syntaxe heredoc.

Comment gérez-vous l'utilisation de longues chaînes multilignes dans vos objets?

Andrew
la source
3
J'avais toujours pensé que \ n était une nouvelle ligne sous Unix \ r est une nouvelle ligne sur MacOS avant OS / X, et \ r \ n est une nouvelle ligne sous Windows. De plus, étant donné qu'il s'agira d'une chaîne qui apparaîtra dans un message électronique, vous voudrez vous assurer que, quelle que soit la manière dont vous le faites, s'affiche correctement sur la plupart des clients de messagerie de commande. Astuce: Outlook supprime les caractères de nouvelle ligne supplémentaires dans certains cas, vous n'obtiendrez donc pas toujours ce que vous attendez.
Kenny Drobnack
1
Je ne sais pas si c'est si important, mais à l'origine, les deux caractères de «nouvelle ligne» venaient de l'époque où vous aviez une machine à écrire physique qui utilisait deux caractères. Un pour remettre le chariot sur le côté gauche de la page (CR - 0xD), et un qui a fait passer la page à la ligne suivante (LF - 0xA.) Je suis sûr qu'il y a des gens qui en savent plus à ce sujet pourtant.
mkgrunder

Réponses:

292

Vous devez utiliser HEREDOC ou 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 différence entre Heredoc et Nowdoc est que le code PHP intégré dans un heredoc est exécuté, tandis que le code PHP dans Nowdoc sera imprimé tel quel.

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

Dans ce cas, $ text aura la valeur My $var.

Remarque: avant la fermeture, EOT;il ne doit y avoir ni espaces ni tabulations. sinon vous obtiendrez une erreur

Halfdan
la source
Pourquoi? Parce que tout entre le premier EOT et le second est considéré comme une chaîne en l'état. Ce qui signifie que vous n'avez pas besoin de mettre une barre oblique inverse n partout dans vos chaînes multilignes. @Fabian: Quelle est la différence entre un HEREDOC et un NOWDOC, ou est-ce la même chose?
Kenny Drobnack
4
@powtac: Non, car il faut que ce soit sur une nouvelle ligne pour mettre fin à un heredoc. Plus précisément, il doit être EOT;sans espace devant lui.
Powerlord
J'ai ajouté une explication pour Nowdoc.
halfdan
6
@halfdan, est-ce que je manque quelque chose? Pourquoi s'embêter avec heredocs et nowdocs quand nous pouvons simplement taper la touche "Entrée" et entourer la chaîne multiligne de guillemets comme une chaîne normale?
Pacerier
3
Veuillez simplement ajouter ceci à votre réponse: avant le dernier, EOT;il ne devrait y avoir ni espaces ni tabulations. sinon vous obtiendrez une erreur.
Shnd
44

J'utilise un système similaire à pix0r et je pense que cela rend le code assez lisible. Parfois, j'allais même jusqu'à séparer les sauts de ligne entre guillemets et utiliser des guillemets simples pour le reste de la chaîne. De cette façon, ils se démarquent du reste du texte et les variables ressortent également mieux si vous utilisez la concaténation plutôt que de les injecter dans une chaîne entre guillemets. Je pourrais donc faire quelque chose comme ça avec votre exemple 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;

En ce qui concerne les sauts de ligne, avec le courrier électronique, vous devez toujours utiliser \ r \ n. PHP_EOL est destiné aux fichiers destinés à être utilisés dans le même système d'exploitation que celui sur lequel s'exécute php.

Cvuorinen
la source
Avez-vous défini cette indentation dans votre IDE (pour définir une chaîne multiligne alignée sur chaque partie)?
Krzysztof Trzos
25

J'utilise des modèles pour du texte long:

email-template.txt contient

hello {name}!
how are you? 

En PHP, je fais ceci:

$email = file_get_contents('email-template.txt');
$email = str_replace('{name},', 'Simon', $email);
Powtac
la source
intéressant ... où stockez-vous vos modèles dans la structure de répertoires d'une application Web?
Andrew
Mon code n'est qu'une démo. Pour une application Web énorme, vous pouvez utiliser une structure telle que / templates / emails /, / templates / userfeedback /. Mais si vous avez plus de choses, je recommanderais un système de modèles complet comme SMARTY.
powtac
Dwoo dwoo.org est un système de templates PHP compatible SMARTY décent que certains considèrent comme un bon successeur (démarré sur PHP5, donc pas de bagage PHP4).
micahwittman
19

Ajout \net / ou\r au milieu de la chaîne, et avoir une très longue ligne de code, comme dans le deuxième exemple, ne se sent pas bien: lorsque vous lisez le code, vous ne voyez pas le résultat, et vous devez faire défiler .

Dans ce genre de situations, j'utilise toujours Heredoc (Ou Nowdoc, si vous utilisez PHP> = 5.3) : facile à écrire, facile à lire, pas besoin de lignes très longues, ...

Par exemple :

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

Juste une chose: le marqueur de fin (et le ' ;' après) doit être la seule chose sur sa ligne: pas d'espace / tabulation avant ou après!

Pascal MARTIN
la source
12

Bien sûr, vous pouvez utiliser HEREDOC, mais en ce qui concerne la lisibilité du code, ce n'est pas vraiment mieux que le premier exemple, enveloppant la chaîne sur plusieurs lignes.

Si vous voulez vraiment que votre chaîne multiligne soit belle et s'harmonise bien avec votre code, je vous recommande de concaténer les chaînes ensemble en tant que telles:

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

Cela peut être légèrement plus lent que HEREDOC ou une chaîne multi-lignes, mais cela fonctionnera bien avec l'indentation de votre code et le rendra plus facile à lire.

pix0r
la source
9

J'aime un peu plus cette méthode pour Javascript mais ça vaut la peine de l'inclure ici car elle n'a pas encore été mentionnée.

$var = "pizza";

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

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

Pour les petites choses, je trouve qu'il est souvent plus facile de travailler avec des structures de tableau que des chaînes concaténées.

Connexes: performances d'implosion vs concat

johnny
la source
1

Celui qui croit que

"abc\n" . "def\n"

La chaîne multiligne est fausse. C'est deux chaînes avec un opérateur de concaténation, pas une chaîne multiligne. De telles chaînes concaténées ne peuvent pas être utilisées comme clés de tableaux prédéfinis, par exemple. Malheureusement, php n'offre pas de vraies chaînes multilignes sous forme de

"abc\n"
"def\n"

uniquement HEREDOCet la NOWDOCsyntaxe, qui convient mieux aux modèles, car le retrait de code imbriqué est interrompu par une telle syntaxe.

Dmitriy Sintsov
la source
1

vous pouvez aussi utiliser:

<?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
la source
0

En ce qui concerne votre question sur les retours à la ligne et les retours chariot:

Je recommanderais d'utiliser la constante globale prédéfinie PHP_EOL car elle résoudra tous les problèmes de compatibilité multiplateforme.

Cette question a été posée au préalable sur SO et vous pouvez trouver plus d'informations en lisant " Quand utiliser la constante PHP PHP_EOL "

Corey Ballou
la source
1
Le commentaire à cette réponse suggère que je devrais utiliser \ r \ n pour les nouvelles lignes dans les e-mails: stackoverflow.com/questions/128560/…
Andrew
0

mais quel est le problème avec les nouvelles lignes et les retours chariot? Quelle est la différence? \ N \ n est-il équivalent à \ r \ r ou \ n \ r? Lequel dois-je utiliser lorsque je crée un espace entre les lignes?

Personne ici ne semblait vraiment répondre à cette question, alors me voici.

\r représente 'retour chariot'

\n représente 'line-feed'

La vraie raison pour eux remonte aux machines à écrire. Au fur et à mesure que vous tapiez, le «chariot» glissait lentement, caractère par caractère, vers la droite de la machine à écrire. Lorsque vous arriviez à la fin de la ligne, vous retourniez le chariot , puis vous passiez à une nouvelle ligne . Pour accéder à la nouvelle ligne, vous basculeriez un levier qui alimentait les lignes vers le graveur de caractères. Ainsi, ces actions, combinées, ont été appelées saut de ligne retour chariot . Donc, littéralement:

Un saut de ligne \n, signifie passer à la ligne suivante.

Un retour chariot \r, signifie déplacer le curseur au début de la ligne.

En fin de compte, Hello\n\nWorlddevrait entraîner la sortie suivante à l'écran:

Hello

     World

Hello\r\rWorlddevrait aboutir à la sortie suivante .

Ce n'est qu'en combinant les 2 caractères \r\nque vous avez la compréhension commune de la ligne connue. IE Hello\r\nWorlddevrait aboutir à:

Hello
World

Et bien sûr, \n\ril en résulterait le même résultat visuel que \r\n.

À l'origine, les ordinateurs ont pris \ret \nlittéralement. Cependant, de nos jours, le soutien pour le retour chariot est rare. Habituellement, sur chaque système, vous pouvez vous en tirer \nseul. Cela ne dépend jamais du système d'exploitation, mais cela dépend de ce que vous visualisez la sortie.

Pourtant, je conseillerais toujours d'utiliser \r\npartout où vous le pouvez!

Sancarn
la source