Tôi bắt đầu tự hỏi những hành vi này hằng số có khi tôi nhìn thấy các hằng số tại trang htmlspecialchars. Tài liệu này là rác, vì vậy tôi bắt đầu đào sâu trong mã nguồn của PHP.
Về cơ bản, các hằng số này ảnh hưởng đến việc một số thực thể nhất định có được mã hóa hay không (hoặc được giải mã cho html_entity_decode
). Hiệu ứng rõ ràng nhất là liệu dấu nháy đơn ('
) được mã hóa thành '
(cho ENT_HTML401
) hoặc '
(đối với những người khác). Tương tự, nó xác định xem '
có được giải mã hay không khi sử dụng html_entity_decode
. ('
luôn được giải mã).
Tất cả các tập quán có thể được tìm thấy trong ext/standard/html.c và tệp tiêu đề của nó. Từ ext/tiêu chuẩn/html.h:
#define ENT_HTML_DOC_HTML401 0
#define ENT_HTML_DOC_XML1 16
#define ENT_HTML_DOC_XHTML 32
#define ENT_HTML_DOC_HTML5 (16|32)
(thay thế ENT_HTML_DOC_
bởi ENT_
để có được PHP họ tên không đổi)
tôi bắt đầu tìm kiếm cho tất cả các lần xuất hiện của những hằng số, và có thể chia sẻ sau đây trên hành vi của các hằng số ENT_*
:
- Nó ảnh hưởng đến thực thể số nào sẽ được giải mã hay không. Ví dụ:

được giải mã thành ký tự không đọc được/không hợp lệ cho ENT_HTML401
và ENT_XHTML
và ENT_XML1
. Tuy nhiên, đối với ENT_HTML5
, đây được coi là ký tự không hợp lệ và do đó nó vẫn là 
. (C function unicode_cp_is_allowed)
- Với
ENT_SUBSTITUTE
bật, trình tự đơn vị mã không hợp lệ cho bộ ký tự được chỉ định được thay thế bằng �
. (không phụ thuộc vào loại tài liệu!)
- Với
ENT_DISALLOWED
bật, mã số không được phép đối với loại tài liệu được chỉ định được thay thế bằng �
. (Không phụ thuộc vào charset!)
- Với
ENT_IGNORE
, trình tự đơn vị mã không hợp lệ tương tự từ ENT_SUBSTITUTE
được loại bỏ và không thay thế được thực hiện (phụ thuộc vào sự lựa chọn của "loại tài liệu", ví dụ như ENT_HTML5
)
- Disallow

cho ENT_HTML5
(line 976)
ENT_XHTML
chia sẻ bản đồ thực thể với ENT_HTML401
.Sự khác biệt duy nhất là '
sẽ được chuyển đổi sang một dấu nháy đơn với ENT_XHTML
khi ENT_HTML401
không chuyển đổi nó (xem this line)
ENT_HTML401
và ENT_XHTML
sử dụng chính xác bản đồ thực thể giống nhau (trừ phần chênh lệch từ quan điểm trước đó). ENT_HTML5
sử dụng bản đồ của riêng nó. Những người khác (hiện tại là ENT_XML1
) có bản đồ giải mã rất hạn chế (>
, &
, <
, '
, "
và số tương đương của chúng). (xem C function unescape_inverse_map)
- Lưu ý cho điểm trước đó: khi chỉ có một vài thực thể phải được thoát (nghĩ về
htmlspecialchars
), tất cả bản đồ thực thể sẽ sử dụng cùng một địa chỉ là ENT_XML1
, ngoại trừ ENT_HTML401
. Người đó sẽ không sử dụng '
, nhưng '
.
Điều đó bao gồm hầu hết mọi thứ. Tôi sẽ không liệt kê tất cả các sự khác biệt của thực thể, thay vào đó tôi muốn trỏ đến https://github.com/php/php-src/tree/php-5.4.11/ext/standard/html_tables đối với một số tệp văn bản chứa ánh xạ cho từng loại.
Tôi nên sử dụng ENT_ * nào cho htmlspecialchars?
Khi sử dụng htmlspecialchars
với ENT_COMPAT (mặc định) hoặc ENT_NOQUOTES, không quan trọng bạn chọn loại nào (xem bên dưới). Tôi thấy một số câu trả lời ở đây trên SO rằng nắm này:
<input value="<?php echo htmlspecialchars($str, ENT_HTML5);?>" >
Đây là không an toàn. Nó sẽ ghi đè lên giá trị mặc định ENT_HTML401 | ENT_COMPAT
có sự khác biệt mà các thực thể HTML5 được sử dụng, nhưng cũng là rằng dấu ngoặc kép không được thoát nữa! Ngoài ra, đây là mã dự phòng. Đối tượng mà phải được mã hóa bởi htmlspecialchars
đều giống nhau cho tất cả ENT_HTML401
, ENT_HTML5
vv
Chỉ cần sử dụng ENT_COMPAT
hoặc ENT_QUOTES
để thay thế. Sau này cũng hoạt động khi bạn sử dụng dấu nháy đơn cho các thuộc tính (value='foo'
). Nếu bạn chỉ có hai đối số cho htmlspecialchars
, không bao gồm đối số vì nó là mặc định (ENT_HTML401
là 0, hãy nhớ?).
Khi bạn muốn in một cái gì đó trên trang (giữa các thẻ, không phải thuộc tính), nó không quan trọng ở tất cả những gì bạn chọn vì nó sẽ có tác dụng như nhau. Nó thậm chí còn đủ để sử dụng ENT_NOQUOTES | ENT_HTML401
bằng với giá trị số 0
.
Xem thêm bên dưới, về ENT_SUBTITUTE và ENT_DISALLOWED.
Tôi nên sử dụng ENT_ * nào cho htmlentities?
Nếu trình soạn thảo văn bản hoặc cơ sở dữ liệu của bạn quá yếu đến nỗi bạn không thể bao gồm các ký tự không phải là US-ASCII (ví dụ: UTF-8), bạn có thể sử dụng htmlentities. Nếu không, hãy lưu một số byte và sử dụng htmlspecialchars (xem ở trên).
Cho dù bạn cần sử dụng ENT_HTML401
, ENT_HTML5
hoặc thứ gì đó khác tùy thuộc vào cách trang của bạn được phân phát. Khi bạn có trang HTML5 (<!doctype html>
), hãy sử dụng ENT_HTML5
. XHTML hoặc XML? Sử dụng ENT_XHTML
hoặc ENT_XML1
tương ứng. Không có tài liệu hoặc HTML đơn giản 'HTML4, hãy sử dụng ENT_HTML401
(đây là mặc định khi bị bỏ qua).
Tôi có nên sử dụng ENT_DISALLOWED, ENT_IGNORE hoặc ENT_SUBSTITUTE không?
Theo mặc định, các chuỗi byte không hợp lệ cho bộ ký tự đã cho bị xóa. Để có một �
ở vị trí của một chuỗi byte không hợp lệ, xác định ENT_SUBSTITUTE
. (Lưu ý rằng &#FFFD;
được hiển thị cho không phải UTF-8 bảng mã). Khi bạn xác định ENT_IGNORE
Mặc dù vậy, những nhân vật này không được hiển thị ngay cả khi bạn chỉ định ENT_SUBSTITUTE
.
Ký tự không hợp lệ cho loại tài liệu được thay thế bởi cùng một ký tự thay thế (hoặc thực thể của nó) ở trên khi ENT_DISALLOWED
được chỉ định. Điều này xảy ra bất kể có tập hợp ENT_IGNORE
(không liên quan gì đến các ký tự không hợp lệ đối với các loại tài liệu).
Trường hợp sử dụng thực sự khá đơn giản: sử dụng cờ thích hợp tùy thuộc vào phương ngữ XML/HTML bạn đang đặt giá trị vào. Tuy nhiên, câu hỏi này đặt ra là: sự khác nhau giữa các quy tắc thoát khỏi phương ngữ HTML/XML là gì? Đó là một câu hỏi hay. – deceze
cảm ơn @deceze, trong trường hợp cụ thể của tôi, (do tác giả là như vậy) những gì được khai báo và văn bản được kiểm tra nhiều lần chưa từng có. Tôi đang điều tra những lá cờ này để xem họ có thể giúp gì không. –