One MUST specify ENT_HTML5 in addition to double_encode=false to avoid double-encoding.The reason is that contrary to the documentation, double_encode=false will NOT unconditionally and globally prevent double-encoding of ALL existing entities. Crucially, it will only skip double-encoding for THOSE character entities that are explicitly valid for the document type chosen!Since ENT_HTML5 references the most expansive list of character entities, it is the only setting that will be most lenient with existing character entities.<?phpdeclare(strict_types=1);$text = 'ampersand(&), double quote("), single quote('), less than(<), greater than(>), numeric entities(&"'<>), HTML 5 entities(+,!$(ņ€)';$result3 = htmlspecialchars( $text, ENT_NOQUOTES | ENT_SUBSTITUTE, 'UTF-8', false );$result4 = htmlspecialchars( $text, ENT_NOQUOTES | ENT_XML1 | ENT_SUBSTITUTE, 'UTF-8', false );$result5 = htmlspecialchars( $text, ENT_NOQUOTES | ENT_XHTML | ENT_SUBSTITUTE, 'UTF-8', false );$result6 = htmlspecialchars( $text, ENT_NOQUOTES | ENT_HTML5 | ENT_SUBSTITUTE, 'UTF-8', false );echo "<br />\r\nHTML 4.01:<br />\r\n", $result3, "<br />\r\nXML 1:<br />\r\n", $result4, "<br />\r\nXHTML:<br />\r\n", $result5, "<br />\r\nHTML 5:<br />\r\n", $result6, "<br />\r\n";?>will produce:HTML 4.01 (will NOT recognize single quote, but Euro):ampersand(&), double quote("), single quote('), less than(<), greater than(>), numeric entities(&"'<>), HTML 5 entities(+,!$(ņ€)XML 1 (WILL recognize single quote, but NOT Euro):ampersand(&), double quote("), single quote('), less than(<), greater than(>), numeric entities(&"'<>), HTML 5 entities(+,!$(ņ€)XHTML (recognizes single quote and Euro):ampersand(&), double quote("), single quote('), less than(<), greater than(>), numeric entities(&"'<>), HTML 5 entities(+,!$(ņ€)HTML 5 (recognizes "all" valid character entities):ampersand(&), double quote("), single quote('), less than(<), greater than(>), numeric entities(&"'<>), HTML 5 entities(+,!$(ņ€)