Menu

Heredoc và nowdoc trong PHP: chuỗi nhiều dòng

Heredoc trong PHP là một chuỗi nhiều dòng bắt đầu bằng <<<EOT và kết thúc bằng EOT; nó thay thế biến giống chuỗi trong ngoặc kép. Nowdoc, <<<'EOT', giữ nguyên văn bản như khi viết. Tìm hiểu cú pháp, quy tắc thụt lề, chèn mảng và đối tượng, cùng template HTML.

Trang này có trình soạn thảo chạy trực tiếp. Sửa, chạy và xem đầu ra ngay lập tức.

Heredoc là một chuỗi nhiều dòng. Bắt đầu bằng <<<EOT, viết văn bản ở các dòng tiếp theo, và kết thúc bằng EOT; trên một dòng riêng. Biến bên trong được thay thế như trong chuỗi ngoặc kép.

Định danh (ở đây là EOT) là một chữ cái hoặc dấu gạch dưới, theo sau là chữ cái, chữ số hoặc dấu gạch dưới. Người ta thường chọn tên nói lên nội dung văn bản: HTML, SQL, TEXT. Một số trình soạn thảo, trong đó có PhpStorm, tô màu phần thân theo ngôn ngữ đó khi tên là HTML hoặc SQL.

Tạo template HTML với heredoc

Heredoc là cách rõ ràng nhất để viết một khối HTML có chèn giá trị, vì mã HTML giữ nguyên hình dạng và không cần escape gì cả. Đầu ra là HTML, nên trình soạn thảo hiển thị nó ở tab Trang.

Có hai chi tiết trong khối code đó: phần tử mảng được bọc trong ngoặc nhọn, {$product['name']}, và ký hiệu đô la trước giá được escape thành \$. Hãy đổi tên hoặc thêm một thẻ rồi chạy lại.

Giá trị đến từ người dùng phải được escape trước khi đưa vào HTML. Xem htmlspecialchars để biết lý do và cách làm.

Nowdoc: văn bản không chèn biến

Nowdoc đặt định danh trong nháy đơn: <<<'EOT'. Không có gì bên trong bị thay thế, nên ký hiệu đô la và dấu gạch chéo ngược giữ nguyên như khi viết. Hãy dùng nó cho code mẫu, biểu thức chính quy và mọi văn bản có chứa $.

Thụt lề dấu kết thúc

Từ PHP 7.3, dấu kết thúc có thể được thụt lề, và phần thụt lề đó sẽ bị bỏ khỏi mọi dòng của thân chuỗi. Nhờ vậy, heredoc nằm trong một hàm hay một câu lệnh if có thể theo đúng thụt lề của code mà khoảng trắng không lọt vào chuỗi.

Dòng json_encode cho thấy kết quả đến từng ký tự: mỗi dòng bị bỏ 8 khoảng trắng, vì TEXT; ở cuối được thụt lề 8.

Một dòng trong thân thụt lề ít hơn dấu kết thúc là lỗi parse:

$html = <<<HTML
  <p>Hello</p>
    HTML;
PHP Parse error:  Invalid body indentation level (expecting an indentation level of at least 4) in /home/index.php on line 3

Mảng, đối tượng và lời gọi phương thức trong heredoc

Heredoc tuân theo cùng quy tắc với chuỗi ngoặc kép. Biến đơn giản dùng trực tiếp được; với khóa mảng có nháy, mảng lồng nhau, thuộc tính và lời gọi phương thức, hãy dùng ngoặc nhọn.

Heredoc làm đối số của hàm

Từ PHP 7.3, sau dấu kết thúc có thể viết tiếp code trên cùng dòng, nên heredoc có thể được truyền thẳng vào một hàm hoặc đặt trong một mảng. Kết hợp với sprintf, bạn có một template mà các placeholder sẽ được điền sau.

Lỗi thường gặp: thiếu dấu chấm phẩy hoặc thừa ký tự sau dấu kết thúc

Định danh kết thúc phải viết đúng y như lúc mở (cùng chữ hoa chữ thường), và những gì theo sau nó trên dòng đó phải hợp lệ trong PHP. EOT; kết thúc một câu lệnh, EOT, tiếp tục một danh sách đối số. Một chữ cái hoặc chữ số ngay sau dấu kết thúc (EOTX;) sẽ làm nó không còn được nhận ra, nên chuỗi kéo dài đến cuối tệp và PHP báo syntax error, unexpected end of file. Cái bẫy ngược lại là một dòng trong thân bắt đầu bằng định danh rồi theo sau là khoảng trắng hoặc dấu câu, như EOT is the marker: nó kết thúc chuỗi quá sớm, và phần còn lại của dòng bị đọc như code PHP (syntax error, unexpected identifier "is"). Hãy chọn một định danh không bao giờ xuất hiện ở đầu dòng trong văn bản, như HTML cho mã HTML hoặc SQL cho truy vấn.

Câu hỏi thường gặp

Heredoc trong PHP là gì?

Một cách viết chuỗi nhiều dòng không cần dấu nháy: bắt đầu bằng <<<EOT và một dấu xuống dòng, viết văn bản, rồi kết thúc bằng EOT; trên một dòng riêng. Biến bên trong được thay thế, y như trong chuỗi ngoặc kép, và bạn có thể dùng thoải mái " và '.

Heredoc và nowdoc khác nhau thế nào?

Heredoc (<<<EOT) thay thế biến và chuỗi escape giống chuỗi ngoặc kép. Nowdoc (<<<'EOT', định danh nằm trong nháy đơn) không làm cả hai việc đó và giữ nguyên mọi $ và dấu gạch chéo ngược như khi viết, giống chuỗi nháy đơn.

Dấu kết thúc heredoc có thụt lề được không?

Được, từ PHP 7.3. Phần thụt lề của dấu kết thúc sẽ bị bỏ khỏi mọi dòng trong thân chuỗi, nên bạn có thể thụt lề heredoc cho khớp với code. Mọi dòng trong thân phải thụt lề ít nhất bằng dấu kết thúc, nếu không PHP dừng với lỗi parse.

Làm sao gọi một hàm bên trong heredoc?

Heredoc chỉ chèn biến, phần tử mảng, thuộc tính và lời gọi phương thức. Hãy gọi hàm trước và lưu kết quả, hoặc giữ tên hàm hay một closure trong biến rồi gọi nó trong cặp ngoặc nhọn: $e = 'htmlspecialchars'; rồi {$e($text)}.

Hình minh họa các ngôn ngữ lập trình của Coddy

Học lập trình cùng Coddy

Bắt đầu