วิธีปฏิบัติที่ดีที่สุด: ทำงานกับสตริงที่ยาวและหลายบรรทัดใน PHP หรือไม่


177

หมายเหตุ: ฉันขอโทษถ้านี่เป็นคำถามที่ง่ายมาก แต่ฉันค่อนข้างย้ำทำมากกว่าการจัดรูปแบบของรหัสของฉัน

ฉันมีคลาสที่มีฟังก์ชั่นที่คืนค่าสตริงที่จะสร้างข้อความเนื้อหาของอีเมล ฉันต้องการรูปแบบข้อความนี้เพื่อให้ถูกต้องในอีเมล แต่ยังไม่ทำให้โค้ดของฉันดูขี้ขลาด นี่คือสิ่งที่ฉันหมายถึง:

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

แต่มันอาจจะเขียนเป็น:

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

แต่อะไรคือข้อตกลงกับสายการบินใหม่และการขึ้นบรรทัดใหม่ ความแตกต่างคืออะไร? คือ\n\nเทียบเท่า\r\rหรือ\n\r? ฉันควรใช้อะไรเมื่อสร้างช่องว่างระหว่างบรรทัด

จากนั้นมีตัวเลือกในการบัฟเฟอร์เอาต์พุตและไวยากรณ์ heredoc

คุณจัดการกับการใช้สตริงหลายบรรทัดในวัตถุของคุณได้อย่างไร?


3
ฉันคิดเสมอว่า \ n เป็นบรรทัดใหม่ใน Unix \ r คือบรรทัดใหม่บน MacOS ก่อน OS / X และ \ r \ n เป็นบรรทัดใหม่ใน Windows นอกจากนี้เมื่อพิจารณาถึงสิ่งนี้จะเป็นสตริงที่ปรากฏในข้อความอีเมลคุณจะต้องตรวจสอบให้แน่ใจว่าวิธีการที่คุณใช้นั้นปรากฏขึ้นอย่างถูกต้องในไคลเอนต์อีเมลคำสั่งส่วนใหญ่ คำแนะนำ: Outlook ลบอักขระบรรทัดใหม่พิเศษในบางกรณีดังนั้นคุณจะไม่ได้รับตามที่คาดหวัง
Kenny Drobnack

1
ไม่แน่ใจว่ามันมีความสำคัญทั้งหมดหรือไม่ แต่ในตอนแรกตัวละคร 'ขึ้นบรรทัดใหม่' ทั้งสองนั้นมาจากเมื่อคุณมีเครื่องพิมพ์ดีดทางกายภาพที่ใช้อักขระสองตัว หนึ่งสำหรับวาง carriage กลับไปที่ด้านซ้ายของหน้า (CR - 0xD) และอีกอันที่ทำให้หน้านั้นไปที่บรรทัดถัดไป (LF - 0xA) ฉันแน่ใจว่ามีคนที่รู้เรื่องนี้มากขึ้น อย่างไรก็ตาม
mkgrunder

คำตอบ:


289

คุณควรใช้ HEREDOC หรือ 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;

ความแตกต่างระหว่าง Heredoc และ Nowdoc ก็คือโค้ด PHP ที่ฝังอยู่ใน heredoc จะถูกดำเนินการในขณะที่โค้ด PHP ใน Nowdoc จะถูกพิมพ์ออกมาตามที่เป็นอยู่

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

ในกรณีนี้ $ My $varข้อความจะมีค่า

หมายเหตุ:ก่อนปิดEOT;จะต้องไม่มีช่องว่างหรือแท็บ มิฉะนั้นคุณจะได้รับข้อผิดพลาด


ทำไม? เพราะทุกอย่างระหว่าง EOT แรกกับสองถือว่าเป็นสตริงตาม - ซึ่งหมายความว่าคุณไม่จำเป็นต้องใส่แบ็กสแลช n ในสตริงหลายบรรทัด @Fabian: ความแตกต่างระหว่าง HEREDOC และ NOWDOC คืออะไรหรือพวกเขาเป็นสิ่งเดียวกัน
Kenny Drobnack

4
@powtac: ไม่เพราะจะต้องอยู่ในบรรทัดใหม่เพื่อสิ้นสุด heredoc โดยเฉพาะจะต้องEOT;ไม่มีช่องว่างก่อนหน้า
Powerlord

ฉันได้เพิ่มคำอธิบายสำหรับ Nowdoc แล้ว
halfdan

6
@halfdan, ฉันหายไปบางอย่าง? ทำไมต้องกังวลกับ heredocs และ nowdocs เมื่อเราสามารถพิมพ์คีย์ "Enter"และล้อมรอบสตริงหลายบรรทัดด้วยเครื่องหมายคำพูดเหมือนกับสตริงปกติ
Pacerier

3
โปรดเพิ่มสิ่งนี้ลงในคำตอบของคุณ: ก่อนหน้าEOT;นี้จะไม่มีการเว้นวรรคหรือแท็บ มิฉะนั้นคุณจะได้รับข้อผิดพลาด
Shnd

44

ฉันใช้ระบบที่คล้ายกันเป็น pix0r และฉันคิดว่านั่นทำให้โค้ดอ่านง่าย บางครั้งฉันก็ไปไกลถึงการแยกการขึ้นบรรทัดใหม่ในเครื่องหมายคำพูดคู่และใช้เครื่องหมายคำพูดเดี่ยวสำหรับส่วนที่เหลือของสตริง วิธีที่พวกเขาโดดเด่นจากส่วนที่เหลือของข้อความและตัวแปรก็โดดเด่นกว่าถ้าคุณใช้การเรียงต่อกันมากกว่าที่จะแทรกพวกมันในสตริงที่ยกมาสองครั้ง ดังนั้นฉันอาจทำอะไรแบบนี้กับตัวอย่างดั้งเดิมของคุณ:

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

เกี่ยวกับการขึ้นบรรทัดใหม่ด้วยอีเมลคุณควรใช้ \ r \ n PHP_EOL สำหรับไฟล์ที่มีไว้เพื่อใช้ในระบบปฏิบัติการเดียวกับที่ php ทำงานอยู่


คุณตั้งค่าการเยื้องใน IDE ของคุณ (เพื่อตั้งค่าสตริงแบบหลายบรรทัดที่จัดแนวกับแต่ละส่วน)
Krzysztof Trzos

25

ฉันใช้เทมเพลตสำหรับข้อความแบบยาว:

email-template.txt มี

hello {name}!
how are you? 

ใน PHP ฉันทำสิ่งนี้:

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

ที่น่าสนใจ ... คุณเก็บแม่แบบของคุณไว้ในโครงสร้างไดเรกทอรีของเว็บแอปพลิเคชันอย่างไร
Andrew

รหัสของฉันเป็นเพียงการสาธิต สำหรับแอปพลิเคชันเว็บขนาดใหญ่คุณอาจใช้โครงสร้างเช่น / templates / อีเมล /, / templates / userfeedback / แต่ถ้าคุณมีสิ่งเพิ่มเติมฉันจะแนะนำระบบแม่แบบเต็มเช่น SMARTY
powtac

Dwoo dwoo.orgเป็นระบบ templating PHP ที่เข้ากันได้กับ SMARTY ที่เหมาะสมซึ่งบางคนคิดว่าเป็นตัวตายตัวแทนที่ดี (เริ่มต้นที่ PHP5 ดังนั้นจึงไม่มีสัมภาระ PHP4)
micahwittman

19

การเพิ่ม\nและ / หรือ\rอยู่ตรงกลางของสตริงและการมีโค้ดยาวมากอย่างเช่นในตัวอย่างที่สองรู้สึกไม่ถูกต้อง: เมื่อคุณอ่านรหัสคุณจะไม่เห็นผลลัพธ์และคุณต้องเลื่อน .

ในสถานการณ์แบบนี้ฉันมักจะใช้ Heredoc (หรือ Nowdoc ถ้าใช้ PHP> = 5.3) : ง่ายต่อการเขียนอ่านง่ายไม่จำเป็นต้องใช้สายยาวมาก ...

ตัวอย่างเช่น

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

มีเพียงสิ่งเดียว: เครื่องหมายสิ้นสุด (และเครื่องหมาย ' ;' หลังจากนั้น) ต้องเป็นสิ่งเดียวที่อยู่ในบรรทัด: ไม่มีช่องว่าง / แท็บก่อนหรือหลัง!


12

แน่นอนว่าคุณสามารถใช้ HEREDOC ได้ แต่ตราบใดที่ความสามารถในการอ่านโค้ดนั้นไม่ได้ดีไปกว่าตัวอย่างแรกแล้วการห่อสตริงข้ามหลายบรรทัด

หากคุณต้องการให้สตริงหลายบรรทัดดูดีและใช้งานได้ดีกับโค้ดของคุณฉันขอแนะนำให้เชื่อมสตริงเข้าด้วยกันดังนี้

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

สิ่งนี้อาจช้ากว่า HEREDOC หรือสตริงแบบหลายบรรทัดเล็กน้อย แต่จะไหลได้ดีกับการเยื้องของโค้ดและทำให้อ่านง่ายขึ้น


9

ฉันชอบวิธีนี้มากกว่า Javascript แต่มันก็คุ้มที่จะรวมไว้ที่นี่เพราะมันยังไม่ได้กล่าวถึง

$var = "pizza";

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

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

สำหรับสิ่งเล็ก ๆ ฉันพบว่าการทำงานกับโครงสร้างอาร์เรย์มักจะง่ายกว่าเมื่อเปรียบเทียบกับสตริงที่ต่อกัน

ที่เกี่ยวข้อง: ประสิทธิภาพของ implode เทียบกับ concat


1

คนที่เชื่อว่า

"abc\n" . "def\n"

เป็นสตริงหลายบรรทัดผิด นั่นคือสองสตริงที่มีตัวดำเนินการเรียงต่อกันไม่ใช่สตริงหลายบรรทัด สตริงที่ต่อกันไม่สามารถใช้เป็นคีย์ของอาร์เรย์ที่กำหนดไว้ล่วงหน้าตัวอย่างเช่น น่าเสียดายที่ php ไม่ได้เสนอสตริงหลายบรรทัดจริงในรูปแบบของ

"abc\n"
"def\n"

เฉพาะHEREDOCและNOWDOCไวยากรณ์ซึ่งเหมาะสำหรับแม่แบบมากขึ้นเพราะเยื้องรหัสซ้อนกันจะถูกทำลายโดยไวยากรณ์ดังกล่าว


1

คุณยังสามารถใช้:

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

เกี่ยวกับคำถามของคุณเกี่ยวกับการขึ้นบรรทัดใหม่และการขึ้นบรรทัดใหม่:

ฉันจะแนะนำให้ใช้PHP_EOLคงที่ทั่วโลกที่กำหนดไว้ล่วงหน้าซึ่งจะแก้ปัญหาความเข้ากันได้ข้ามแพลตฟอร์มใด ๆ

คำถามนี้ได้รับการยกใน SO ล่วงหน้าและคุณสามารถหาข้อมูลเพิ่มเติมโดยการอ่าน " ฉันจะใช้ PHP คงที่ PHP_EOL เมื่อใด "


1
ความคิดเห็นต่อคำตอบนี้ชี้ให้เห็นว่าฉันควรใช้ \ r \ n สำหรับบรรทัดใหม่ในอีเมล: stackoverflow.com/questions/128560/…
Andrew

0

แต่อะไรคือข้อตกลงกับสายการบินใหม่และการขึ้นบรรทัดใหม่ ความแตกต่างคืออะไร? \ n \ n เทียบเท่ากับ \ r \ r หรือ \ n \ r หรือไม่ ฉันควรใช้อะไรเมื่อสร้างช่องว่างระหว่างบรรทัด

ไม่มีใครที่นี่ดูเหมือนจะตอบคำถามนี้จริงดังนั้นที่นี่ฉัน

\r แสดงถึง 'carriage-return'

\n แทน 'ฟีดบรรทัด'

เหตุผลที่แท้จริงสำหรับพวกเขากลับไปที่เครื่องพิมพ์ดีด เมื่อคุณพิมพ์ 'carriage' จะค่อยๆเลื่อนทีละตัวอักษรไปทางขวาของเครื่องพิมพ์ดีด เมื่อคุณมีการจุดสิ้นสุดของบรรทัดที่คุณจะกลับรถแล้วไปที่บรรทัดใหม่ หากต้องการไปยังบรรทัดใหม่คุณจะต้องพลิกคันโยกซึ่งป้อนสายไปที่ตัวเขียนชนิด ดังนั้นการกระทำเหล่านี้รวมกันเรียกว่าการขึ้นบรรทัดใหม่อาหารเส้นกลับสายการบินดังนั้นแท้จริง:

การป้อนบรรทัด\nหมายถึงการย้ายไปยังบรรทัดถัดไป

กลับรถ\rหมายถึงการเคลื่อนย้ายเคอร์เซอร์ไปยังจุดเริ่มต้นของบรรทัด

ในที่สุดHello\n\nWorldควรส่งผลให้ผลลัพธ์ต่อไปนี้บนหน้าจอ:

Hello

     World

โดยที่Hello\r\rWorldควรส่งผลให้ผลลัพธ์ต่อไปนี้การส่งออกต่อไป

เมื่อรวมสองตัวละคร\r\nที่คุณมีความเข้าใจร่วมกันของสายรู้ IE Hello\r\nWorldควรส่งผลให้:

Hello
World

และแน่นอนว่า\n\rจะส่งผลให้เห็นภาพเหมือน\r\nกัน

เดิมทีคอมพิวเตอร์ใช้\rและ\nค่อนข้างแท้จริง อย่างไรก็ตามในทุกวันนี้การรองรับการรับคืนของรถกระจัดกระจาย โดยปกติแล้วในทุกระบบที่คุณสามารถใช้งานได้\nเอง ไม่เคยขึ้นอยู่กับระบบปฏิบัติการ แต่ขึ้นอยู่กับสิ่งที่คุณกำลังรับชม

ยังฉันมักจะแนะนำให้ใช้\r\nทุกที่ที่คุณสามารถ!

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.