Praktik Terbaik: bekerja dengan string multiline yang panjang di PHP?

177

Catatan: Saya minta maaf jika ini adalah pertanyaan yang sangat sederhana tapi saya agak obsesif kompulsif atas pemformatan kode saya.

Saya memiliki kelas yang memiliki fungsi yang mengembalikan string yang akan membentuk teks isi email. Saya ingin teks ini diformat sehingga terlihat benar di email, tetapi juga agar tidak membuat kode saya terlihat funky. Inilah yang saya maksud:

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

tetapi bisa juga ditulis sebagai:

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

tapi apa masalahnya dengan jalur baru dan pengembalian carriage? Apa bedanya? Apakah \n\nsetara dengan \r\ratau \n\r? Mana yang harus saya gunakan ketika saya membuat celah garis di antara garis?

Lalu ada opsi output buffering dan sintaks heredoc.

Bagaimana Anda berurusan dengan menggunakan string multiline panjang di objek Anda?

Andrew
sumber
3
Saya selalu berpikir bahwa \ n adalah baris baru di Unix adalah baris baru di MacOS sebelum OS / X, dan baris baru di Windows. Selain itu, mengingat ini akan menjadi string yang muncul dalam pesan email, Anda harus memastikan bahwa cara apa pun yang Anda lakukan itu muncul dengan benar pada sebagian besar klien surat perintah. Petunjuk: Outlook menghapus karakter baris baru ekstra dalam beberapa kasus, sehingga Anda tidak akan selalu mendapatkan apa yang Anda harapkan.
Kenny Drobnack
1
Tidak yakin apakah itu yang paling penting, tetapi awalnya dua karakter 'baris baru' berasal dari ketika Anda memiliki mesin tik fisik yang menggunakan dua karakter. Satu untuk meletakkan kereta kembali ke sisi kiri halaman (CR - 0xD), dan satu yang menyebabkan halaman untuk pergi ke baris berikutnya (LF - 0xA.) Saya yakin ada orang yang tahu lebih banyak tentang ini namun.
mkgrunder

Jawaban:

288

Anda harus menggunakan HEREDOC atau 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;

Perbedaan antara Heredoc dan Nowdoc adalah kode PHP yang tertanam dalam heredoc dieksekusi, sedangkan kode PHP di Nowdoc akan dicetak apa adanya.

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

Dalam hal ini $ text akan memiliki nilai My $var.

Catatan: sebelum penutupan EOT;tidak boleh ada spasi atau tab. jika tidak, Anda akan mendapatkan kesalahan

halfdan
sumber
Mengapa? Karena segala sesuatu antara EOT pertama dan kedua dianggap sebagai string apa adanya. Yang berarti Anda tidak perlu meletakkan backslash di seluruh string multi-line Anda. @Fabian: Apa perbedaan antara HEREDOC dan NOWDOC, atau apakah keduanya sama?
Kenny Drobnack
4
@ Powow: Tidak, karena harus berada di jalur baru untuk mengakhiri heredoc. Secara khusus, harus EOT;tanpa spasi sebelum itu.
Powerlord
Saya telah menambahkan penjelasan untuk Nowdoc.
halfdan
6
@halfdan, Apakah saya kehilangan sesuatu? Mengapa repot-repot dengan heredocs dan nowdocs ketika kita cukup mengetik tombol "Enter" dan mengelilingi string multi-line dengan tanda kutip seperti string normal?
Pacerier
3
Harap tambahkan ini ke jawaban Anda: sebelum yang terakhir EOT;seharusnya tidak ada spasi atau tab. jika tidak, Anda akan mendapatkan kesalahan.
Shnd
44

Saya menggunakan sistem yang mirip dengan pix0r dan saya pikir itu membuat kode ini cukup mudah dibaca. Kadang-kadang saya benar-benar pergi sejauh memisahkan jeda baris dalam tanda kutip ganda dan menggunakan tanda kutip tunggal untuk sisa string. Dengan cara itu mereka menonjol dari sisa teks dan variabel juga menonjol lebih baik jika Anda menggunakan penggabungan daripada menyuntikkan mereka ke dalam string yang dikutip ganda. Jadi saya mungkin melakukan sesuatu seperti ini dengan contoh asli Anda:

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

Mengenai jeda baris, dengan email Anda harus selalu menggunakan \ r \ n. PHP_EOL adalah untuk file yang dimaksudkan untuk digunakan dalam sistem operasi yang sama dengan yang digunakan php.

Cvuorinen
sumber
Apakah Anda mengatur lekukan itu di IDE Anda (untuk mengatur string multilined yang diluruskan ke setiap bagian)?
Krzysztof Trzos
25

Saya menggunakan templat untuk teks panjang:

email-template.txt berisi

hello {name}!
how are you? 

Dalam PHP saya melakukan ini:

$email = file_get_contents('email-template.txt');
$email = str_replace('{name},', 'Simon', $email);
powtac
sumber
menarik ... di mana Anda menyimpan template Anda dalam struktur direktori aplikasi web?
Andrew
Kode saya hanya demo. Untuk aplikasi web besar, Anda dapat menggunakan struktur seperti / templates / email /, / templates / userfeedback /. Tetapi jika Anda memiliki lebih banyak barang, saya akan merekomendasikan sistem template lengkap seperti SMARTY.
powtac
Dwoo dwoo.org adalah sistem templating PHP yang kompatibel dengan SMARTY yang layak, yang oleh beberapa orang dianggap sebagai penerus yang baik (dimulai dari PHP5, jadi tidak ada bagasi PHP4).
micahwittman
19

Menambahkan \ndan / atau \rdi tengah-tengah string, dan memiliki garis kode yang sangat panjang, seperti pada contoh kedua, tidak terasa benar: ketika Anda membaca kode, Anda tidak melihat hasilnya, dan Anda harus menggulir .

Dalam situasi seperti ini, saya selalu menggunakan Heredoc (Atau Nowdoc, jika menggunakan PHP> = 5.3) : mudah ditulis, mudah dibaca, tidak perlu baris super panjang, ...

Misalnya :

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

Hanya satu hal: penanda akhir (dan tanda ' ;' setelahnya) harus menjadi satu-satunya hal di barisnya: tidak ada spasi / tab sebelum atau sesudah!

Pascal MARTIN
sumber
12

Tentu, Anda bisa menggunakan HEREDOC, tetapi sejauh pembacaan kode tidak benar-benar lebih baik daripada contoh pertama, membungkus string melintasi beberapa baris.

Jika Anda benar-benar ingin string multi-line Anda terlihat bagus dan mengalir dengan baik dengan kode Anda, saya sarankan merangkai string bersama sebagai berikut:

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

Ini mungkin sedikit lebih lambat daripada HEREDOC atau string multi-line, tetapi itu akan mengalir dengan baik dengan lekukan kode Anda dan membuatnya lebih mudah dibaca.

pix0r
sumber
9

Saya suka metode ini sedikit lebih untuk Javascript tetapi tampaknya layak termasuk di sini karena belum disebutkan.

$var = "pizza";

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

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

Untuk hal-hal yang lebih kecil, saya merasa sering lebih mudah untuk bekerja dengan struktur array dibandingkan dengan string yang digabungkan.

Terkait: kinerja implode vs concat

johnny
sumber
1

Orang yang percaya itu

"abc\n" . "def\n"

adalah string multiline salah. Itu dua string dengan operator concatenation, bukan string multiline. String bersambung seperti itu tidak dapat digunakan sebagai kunci dari array yang telah ditentukan, misalnya. Sayangnya php tidak menawarkan string multiline nyata dalam bentuk

"abc\n"
"def\n"

hanya HEREDOCdan NOWDOCsintaksis, yang lebih cocok untuk templat, karena indentasi kode bersarang rusak oleh sintaksis seperti itu.

Dmitriy Sintsov
sumber
1

Anda juga bisa menggunakan:

<?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
sumber
0

Sehubungan dengan pertanyaan Anda tentang baris baru dan pengembalian carriage:

Saya akan merekomendasikan menggunakan konstanta global PHP_EOL yang telah ditentukan karena akan menyelesaikan masalah kompatibilitas lintas platform.

Pertanyaan ini telah diajukan pada SO sebelumnya dan Anda dapat menemukan informasi lebih lanjut dengan membaca " Kapan saya menggunakan konstanta PHP PHP_EOL "

Corey Ballou
sumber
1
Komentar untuk jawaban ini menunjukkan bahwa saya harus menggunakan \ r \ n untuk baris baru dalam email: stackoverflow.com/questions/128560/…
Andrew
0

tapi apa masalahnya dengan jalur baru dan pengembalian carriage? Apa bedanya? Apakah \ n \ n sama dengan \ r \ r atau \ n \ r? Mana yang harus saya gunakan ketika saya membuat celah garis di antara garis?

Tampaknya tidak ada seorang pun di sini yang menjawab pertanyaan ini, jadi inilah saya.

\r mewakili 'carriage-return'

\n mewakili 'umpan baris'

Alasan sebenarnya mereka kembali ke mesin tik. Saat Anda mengetik 'carriage' perlahan-lahan akan meluncur, karakter demi karakter, di sebelah kanan mesin tik. Ketika Anda sampai di ujung garis Anda akan mengembalikan kereta dan kemudian pergi ke jalur baru . Untuk menuju ke baris baru, Anda akan membalik tuas yang diumpankan ke penulis tipe. Dengan demikian tindakan-tindakan ini, digabungkan, disebut pengumpanan carriage return line . Secara harfiah:

Umpan baris \n,, berarti pindah ke baris berikutnya.

Carriage return,, \rberarti memindahkan kursor ke awal baris.

Pada akhirnya Hello\n\nWorldharus menghasilkan output berikut di layar:

Hello

     World

Dimana sebagai Hello\r\rWorld harus menghasilkan output berikut .

Hanya ketika menggabungkan 2 karakter \r\nyang Anda memiliki pemahaman umum tentang garis tahu. YAITUHello\r\nWorld harus menghasilkan:

Hello
World

Dan tentu saja \n\r akan menghasilkan keluaran visual yang sama dengan \r\n.

Awalnya komputer mengambil \r dan \nsecara harfiah. Namun belakangan ini dukungan untuk carriage return jarang. Biasanya pada setiap sistem Anda dapat menggunakan \ndengan sendirinya. Itu tidak pernah tergantung pada OS, tetapi itu tergantung pada apa yang Anda lihat output masuk

Tetap saya selalu menyarankan menggunakan \r\ndimanapun Anda bisa!

Sancarn
sumber