Thực tiễn tốt nhất: làm việc với các chuỗi dài, đa dòng trong PHP?


177

Lưu ý: Tôi xin lỗi nếu đây là một câu hỏi cực kỳ đơn giản nhưng tôi hơi bị ám ảnh về định dạng mã của mình.

Tôi có một lớp có một hàm trả về một chuỗi sẽ tạo thành văn bản cơ thể của một email. Tôi muốn văn bản này được định dạng để nó trông đúng trong email, nhưng cũng vì vậy nó không làm cho mã của tôi trông thú vị. Ý tôi là đây:

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

nhưng nó cũng có thể được viết là:

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

Nhưng những gì đối phó với các dòng mới và vận chuyển trở lại? Có gì khác biệt? Là \n\ntương đương \r\rhay \n\r? Tôi nên sử dụng khi nào tôi tạo khoảng cách giữa các dòng?

Sau đó, có tùy chọn bộ đệm đầu ra và cú pháp heredoc.

Làm thế nào để bạn đối phó với việc sử dụng chuỗi multiline dài trong các đối tượng của bạn?


3
Tôi luôn nghĩ rằng \ n là dòng mới trong Unix \ r là dòng mới trên MacOS trước OS / X và \ r \ n là dòng mới trên Windows. Ngoài ra, xem xét đây sẽ là một chuỗi hiển thị trong thông báo email, bạn sẽ muốn đảm bảo rằng bất cứ cách nào bạn đang thực hiện đều hiển thị chính xác trên hầu hết các ứng dụng thư khách. Gợi ý: Outlook sẽ xóa các ký tự dòng mới bổ sung trong một số trường hợp, do đó bạn sẽ không nhận được những gì bạn mong đợi.
Kenny Drobnack

1
Không chắc nó có quan trọng không, nhưng ban đầu hai ký tự 'dòng mới' xuất phát từ khi bạn có một máy đánh chữ vật lý sử dụng hai ký tự. Một để đưa cỗ xe trở lại phía bên trái của trang (CR - 0xD), và một khiến cho trang đi đến dòng tiếp theo (LF - 0xA.) Tôi chắc chắn có những người biết nhiều hơn về điều này Tuy nhiên.
mkgrunder

Câu trả lời:


288

Bạn nên sử dụng HEREDOC hoặc 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;

Sự khác biệt giữa Heredoc và Nowdoc là mã PHP được nhúng trong một di sản được thực thi, trong khi mã PHP trong Nowdoc sẽ được in ra.

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

Trong trường hợp này $ text sẽ có giá trị My $var.

Lưu ý: trước khi đóng EOT;sẽ không có khoảng trắng hoặc tab. nếu không bạn sẽ gặp lỗi


Tại sao? Bởi vì mọi thứ giữa EOT đầu tiên và thứ hai được coi là một chuỗi như hiện trạng. Điều đó có nghĩa là bạn không cần đặt dấu gạch chéo ngược trên tất cả các chuỗi nhiều dòng của bạn. @Fabian: Sự khác biệt giữa HEREDOC và NOWDOC, hoặc chúng là cùng một thứ?
Kenny Drobnack

4
@powtac: Không, bởi vì nó phải ở trên một dòng mới để kết thúc một di sản. Cụ thể, nó phải EOT;không có khoảng trống trước nó.
Powerlord

Tôi đã thêm một lời giải thích cho Nowdoc.
Halfdan

6
@halfdan, tôi có thiếu thứ gì không? Tại sao phải bận tâm với heredocs và nowdocs khi chúng ta chỉ cần gõ phím "Enter" và bao quanh chuỗi nhiều dòng với dấu ngoặc kép giống như một chuỗi bình thường?
Pacerier

3
Chỉ cần vui lòng thêm câu này vào câu trả lời của bạn: trước cuối cùng EOT;sẽ không có khoảng trắng hoặc tab. nếu không bạn sẽ gặp lỗi
Shnd 7/12/2016

44

Tôi sử dụng hệ thống tương tự như pix0r và tôi nghĩ rằng điều đó làm cho mã khá dễ đọc. Đôi khi tôi thực sự sẽ đi xa đến mức tách các ngắt dòng trong dấu ngoặc kép và sử dụng dấu ngoặc đơn cho phần còn lại của chuỗi. Bằng cách đó, chúng nổi bật so với phần còn lại của văn bản và các biến cũng nổi bật hơn nếu bạn sử dụng phép nối thay vì đưa chúng vào trong chuỗi trích dẫn kép. Vì vậy, tôi có thể làm một cái gì đó như thế này với ví dụ ban đầu của bạn:

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

Về ngắt dòng, với email, bạn phải luôn sử dụng \ r \ n. PHP_EOL dành cho các tệp được sử dụng trong cùng hệ điều hành mà php đang chạy.


Bạn đã đặt thụt lề đó trong IDE của mình (để đặt chuỗi nhiều dòng được căn chỉnh theo từng phần)?
Krzysztof Trzos

25

Tôi sử dụng các mẫu cho văn bản dài:

email-template.txt chứa

hello {name}!
how are you? 

Trong PHP tôi làm điều này:

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

thú vị ... bạn lưu mẫu ở đâu trong cấu trúc thư mục của ứng dụng web?
Andrew

Mã của tôi chỉ là một bản demo. Đối với một ứng dụng web lớn, bạn có thể sử dụng cấu trúc như / samples / email /, / samples / userfeedback /. Nhưng nếu bạn có nhiều thứ hơn, tôi sẽ đề xuất một hệ thống mẫu đầy đủ như SMARTY.
powtac

Dwoo dwoo.org là một hệ thống tạo khuôn mẫu PHP tương thích SMARTY phong nha mà một số người coi là một người kế thừa tốt (bắt đầu trên PHP5, vì vậy không có hành lý PHP4).
micahwittman

19

Thêm \nvà / hoặc \rở giữa chuỗi và có một dòng mã rất dài, như trong ví dụ thứ hai, không cảm thấy đúng: khi bạn đọc mã, bạn không thấy kết quả và bạn phải cuộn .

Trong loại tình huống này, tôi luôn sử dụng Heredoc (Hoặc Nowdoc, nếu sử dụng PHP> = 5.3) : dễ viết, dễ đọc, không cần các dòng siêu dài, ...

Ví dụ :

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

Chỉ một điều: điểm đánh dấu kết thúc (và ' ;' sau nó) phải là điều duy nhất trên dòng của nó: không có khoảng trắng / tab trước hoặc sau!


12

Chắc chắn, bạn có thể sử dụng HEREDOC, nhưng về khả năng đọc mã, nó không thực sự tốt hơn ví dụ đầu tiên, gói chuỗi trên nhiều dòng.

Nếu bạn thực sự muốn chuỗi nhiều dòng của bạn trông đẹp và lưu chuyển tốt với mã của bạn, tôi khuyên bạn nên kết hợp các chuỗi với nhau như sau:

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

Điều này có thể chậm hơn một chút so với HEREDOC hoặc một chuỗi nhiều dòng, nhưng nó sẽ lưu chuyển tốt với sự thụt dòng mã của bạn và giúp dễ đọc hơn.


9

Tôi thích phương pháp này hơn một chút cho Javascript nhưng có vẻ đáng giá bao gồm cả ở đây vì nó chưa được đề cập.

$var = "pizza";

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

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

Đối với những thứ nhỏ hơn, tôi thấy nó thường dễ dàng hơn để làm việc với các cấu trúc mảng so với các chuỗi được nối.

Liên quan: hiệu suất implode vs concat


1

Người tin rằng

"abc\n" . "def\n"

là chuỗi multiline là sai. Đó là hai chuỗi với toán tử nối, không phải là chuỗi đa dòng. Các chuỗi nối như vậy không thể được sử dụng làm khóa của các mảng được xác định trước, ví dụ. Thật không may, php không cung cấp các chuỗi đa dòng thực sự ở dạng

"abc\n"
"def\n"

chỉ HEREDOCNOWDOCcú pháp, phù hợp hơn cho các mẫu, vì thụt mã lồng nhau bị phá vỡ bởi cú pháp đó.


1

bạn cũng có thể dùng:

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

Liên quan đến câu hỏi của bạn về dòng mới và lợi nhuận vận chuyển:

Tôi khuyên bạn nên sử dụng hằng số toàn cầu PHP_EOL được xác định trước vì nó sẽ giải quyết mọi vấn đề tương thích đa nền tảng.

Câu hỏi này đã được nêu ra trên SO trước đó và bạn có thể tìm hiểu thêm thông tin bằng cách đọc " Khi nào tôi sử dụng hằng số PHP_EOL PHP "


1
Nhận xét cho câu trả lời này gợi ý rằng tôi nên sử dụng \ r \ n cho các dòng mới trong email: stackoverflow.com/questions/128560/ợi
Andrew

0

Nhưng những gì đối phó với các dòng mới và vận chuyển trở lại? Có gì khác biệt? Là \ n \ n tương đương với \ r \ r hay \ n \ r? Tôi nên sử dụng khi nào tôi tạo khoảng cách giữa các dòng?

Không ai ở đây dường như thực sự trả lời câu hỏi này, vì vậy tôi ở đây.

\r đại diện cho 'vận chuyển trở lại'

\n đại diện cho 'line-feed'

Lý do thực sự cho họ quay trở lại máy chữ. Khi bạn gõ 'cỗ xe' sẽ từ từ trượt, theo từng ký tự, ở bên phải của máy đánh chữ. Khi bạn đã đến cuối dòng, bạn sẽ trả lại xe ngựa và sau đó đi đến một dòng mới . Để đi đến dòng mới, bạn sẽ lật một đòn bẩy cung cấp các dòng cho nhà văn loại. Do đó, những hành động này, được kết hợp, được gọi là nguồn cấp dữ liệu dòng vận chuyển . Vì vậy, hoàn toàn theo nghĩa đen:

Một nguồn cấp dữ liệu, \ncó nghĩa là di chuyển đến dòng tiếp theo.

Một sự trở lại vận chuyển \r, có nghĩa là di chuyển con trỏ đến đầu dòng.

Cuối cùng Hello\n\nWorldsẽ dẫn đến kết quả đầu ra sau trên màn hình:

Hello

     World

Trường hợp như Hello\r\rWorldvậy sẽ dẫn đến đầu ra sau đây .

Chỉ khi kết hợp 2 ký tự \r\nmà bạn có sự hiểu biết chung về dòng đã biết. IE Hello\r\nWorldsẽ dẫn đến:

Hello
World

Và tất nhiên \n\rsẽ dẫn đến kết quả hình ảnh tương tự như \r\n.

Ban đầu máy tính lấy \r\nhoàn toàn theo nghĩa đen. Tuy nhiên những ngày này sự hỗ trợ cho việc vận chuyển trở lại rất thưa thớt. Thông thường trên mọi hệ thống bạn có thể \ntự mình sử dụng . Nó không bao giờ phụ thuộc vào HĐH, nhưng nó phụ thuộc vào những gì bạn đang xem đầu ra.

Tuy nhiên, tôi luôn khuyên bạn nên sử dụng \r\nbất cứ nơi nào bạn có thể!

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.