Best practice: lavorare con stringhe lunghe e multilinea in PHP?


177

Nota: mi dispiace se questa è una domanda estremamente semplice, ma sono un po 'ossessivo compulsivo sulla formattazione del mio codice.

Ho una classe che ha una funzione che restituisce una stringa che comporrà il corpo del testo di una e-mail. Voglio che questo testo sia formattato in modo che appaia nell'e-mail, ma anche in modo che il mio codice non appaia strano. Ecco cosa intendo:

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

ma potrebbe anche essere scritto come:

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

ma qual è il problema con le nuove linee e i resi di trasporto? Qual è la differenza? È \n\nl'equivalente di \r\ro \n\r? Quale dovrei usare quando sto creando uno spazio tra le linee?

Quindi c'è l'opzione di buffering dell'output e sintassi ereditaria.

Come gestisci l'utilizzo di lunghe stringhe multilinea nei tuoi oggetti?


3
Ho sempre pensato che \ n era newline in Unix \ è newline su MacOS prima di OS / X e \ r \ n è newline su Windows. Inoltre, considerando che questa sarà una stringa che viene visualizzata in un messaggio di posta elettronica, ti consigliamo di assicurarti che qualunque modo tu lo faccia, viene visualizzato correttamente sulla maggior parte dei client di posta di comando. Suggerimento: Outlook rimuove i caratteri di nuova riga extra in alcuni casi, quindi non otterrai sempre ciò che ti aspetti.
Kenny Drobnack,

1
Non sono sicuro che sia così importante, ma originariamente i due personaggi "newline" provenivano da quando avevi una macchina da scrivere fisica che utilizzava due personaggi. Uno per rimettere il carrello sul lato sinistro della pagina (CR - 0xD) e uno che ha portato la pagina alla riga successiva (LF - 0xA.) Sono sicuro che ci sono persone che ne sanno di più riguardo a questo però.
mkgrunder,

Risposte:


289

È necessario utilizzare HEREDOC o 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 differenza tra Heredoc e Nowdoc è che il codice PHP incorporato in un heredoc viene eseguito, mentre il codice PHP in Nowdoc verrà stampato così com'è.

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

In questo caso $ text avrà il valore My $var.

Nota: prima della chiusura EOT;non dovrebbero esserci spazi o tabulazioni. altrimenti riceverai un errore


Perché? Perché tutto tra il primo EOT e il secondo è considerato una stringa così com'è. Ciò significa che non è necessario inserire una barra rovesciata su tutte le stringhe multilinea. @Fabian: Qual è la differenza tra un HEREDOC e NOWDOC o sono la stessa cosa?
Kenny Drobnack,

4
@powtac: No, perché deve essere su una nuova linea per porre fine a una eredità. In particolare, deve essere EOT;senza spazi prima.
Powerlord il

Ho aggiunto una spiegazione per Nowdoc.
halfdan

6
@halfdan, mi sto perdendo qualcosa? Perché preoccuparsi di heredocs e nowdocs quando possiamo semplicemente digitare il tasto "Invio" e racchiudere la stringa multilinea tra virgolette proprio come una normale stringa?
Pacerier,

3
Per favore, aggiungi questo alla tua risposta: prima dell'ultimo EOT;non ci dovrebbero essere spazi o tab. altrimenti riceverai un errore.
Shnd

44

Uso un sistema simile a pix0r e penso che renda il codice abbastanza leggibile. A volte in realtà andrei fino a separare le interruzioni di riga tra virgolette doppie e utilizzare le virgolette singole per il resto della stringa. In questo modo si distinguono dal resto del testo e anche le variabili si distinguono meglio se si utilizza la concatenazione anziché iniettarle all'interno di una stringa tra virgolette doppie. Quindi potrei fare qualcosa del genere con il tuo esempio originale:

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

Per quanto riguarda le interruzioni di riga, con l'email dovresti sempre usare \ r \ n. PHP_EOL è per i file che devono essere utilizzati nello stesso sistema operativo su cui è in esecuzione php.


Hai impostato quella rientranza nel tuo IDE (per impostare una stringa multilinea allineata a ciascuna parte)?
Krzysztof Trzos,

25

Uso i modelli per testi lunghi:

email-template.txt contiene

hello {name}!
how are you? 

In PHP lo faccio:

$email = file_get_contents('email-template.txt');
$email = str_replace('{name},', 'Simon', $email);

interessante ... dove memorizzi i tuoi template nella struttura delle directory di un'applicazione web?
Andrew,

Il mio codice è solo una demo. Per un'app Web di grandi dimensioni è possibile utilizzare una struttura come / templates / email /, / templates / userfeedback /. Ma se hai più cose, consiglierei un sistema di template completo come SMARTY.
powtac,

Dwoo dwoo.org è un discreto sistema di template PHP compatibile con SMARTY che alcuni considerano un buon successore (avviato su PHP5, quindi nessun bagaglio PHP4).
micahwittman,

19

Aggiungere \ne / o \rnel mezzo della stringa e avere una riga di codice molto lunga, come nel secondo esempio, non sembra corretto: quando leggi il codice, non vedi il risultato e devi scorrere .

In questo tipo di situazioni, utilizzo sempre Heredoc (o Nowdoc, se utilizzo PHP> = 5.3) : facile da scrivere, facile da leggere, senza bisogno di righe super-lunghe, ...

Per esempio :

$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: il marker di fine (e il ' ;' dopo di esso) deve essere l'unica cosa sulla sua linea: nessuno spazio / scheda prima o dopo!


12

Certo, potresti usare HEREDOC, ma per quanto riguarda la leggibilità del codice non è davvero meglio del primo esempio, avvolgendo la stringa su più righe.

Se vuoi davvero che la tua stringa multilinea abbia un bell'aspetto e scorra bene con il tuo codice, ti consiglio di concatenare le stringhe come tali:

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

Potrebbe essere leggermente più lento di HEREDOC o di una stringa a più righe, ma scorrerà bene con il rientro del codice e renderà più semplice la lettura.


9

Mi piace un po 'di più questo metodo per Javascript, ma sembra che valga la pena includerlo qui perché non è stato ancora menzionato.

$var = "pizza";

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

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

Per le cose più piccole, trovo che sia spesso più facile lavorare con strutture array rispetto alle stringhe concatenate.

Correlati: implode vs concat performance


1

Colui che lo crede

"abc\n" . "def\n"

la stringa multilinea è errata. Sono due stringhe con operatore di concatenazione, non una stringa multilinea. Ad esempio, tali stringhe concatenate non possono essere utilizzate come chiavi di array predefiniti. Sfortunatamente php non offre stringhe multilinea reali sotto forma di

"abc\n"
"def\n"

solo HEREDOCe NOWDOCsintassi, che è più adatta per i modelli, poiché il rientro del codice nidificato viene interrotto da tale sintassi.


1

puoi anche usare:

<?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();

0

Per quanto riguarda la tua domanda su newline e resi di trasporto:

Consiglio di utilizzare la costante globale predefinita PHP_EOL in quanto risolverà eventuali problemi di compatibilità multipiattaforma.

Questa domanda è stata sollevata in anticipo su SO e puoi trovare maggiori informazioni leggendo " Quando uso la costante PHP PHP_EOL "


1
Il commento a questa risposta suggerisce che dovrei usare \ r \ n per le nuove righe nelle e-mail: stackoverflow.com/questions/128560/…
Andrew

0

ma qual è il problema con le nuove linee e i resi di trasporto? Qual è la differenza? \ N \ n è l'equivalente di \ r \ r o \ n \ r? Quale dovrei usare quando sto creando uno spazio tra le linee?

Nessuno qui sembrava effettivamente rispondere a questa domanda, quindi eccomi qui.

\r rappresenta "ritorno a capo"

\n rappresenta "avanzamento riga"

Il vero motivo per loro risale alle macchine da scrivere. Mentre scrivevi, la 'carrozza' scivolava lentamente, carattere per carattere, a destra della macchina da scrivere. Quando arrivate alla fine della linea, restituireste il trasporto e poi passate a una nuova linea . Per andare alla nuova linea, devi girare una leva che alimenta le linee allo scrittore di caratteri. Pertanto, queste azioni, combinate, venivano chiamate feed line di ritorno carrello . Quindi letteralmente:

Un avanzamento riga \n, significa passare alla riga successiva.

Un ritorno a capo \r, significa spostare il cursore all'inizio della riga.

Alla fine Hello\n\nWorlddovrebbe risultare il seguente output sullo schermo:

Hello

     World

Dove come Hello\r\rWorlddovrebbe comportare il seguente output .

È solo quando combini i 2 personaggi \r\nche hai la comprensione comune della linea conosciuta. IE Hello\r\nWorlddovrebbe comportare:

Hello
World

E ovviamente \n\rsi tradurrebbe nello stesso output visivo di \r\n.

Inizialmente i computer prendevano \re \nletteralmente. Tuttavia in questi giorni il supporto per il ritorno a capo è scarso. Di solito su ogni sistema con cui puoi cavartela da \nsolo. Non dipende mai dal sistema operativo, ma dipende da cosa stai visualizzando l'output.

Ti consiglio comunque di usare \r\novunque tu sia!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.