Signature
mb_encode_numericentity(
string $string,
array $map,
?string $encoding = null,
bool $hex = false
): stringPurpose
mb_encode_numericentity() replaces selected characters in a string with HTML numeric character references such as é or é. You choose which characters are replaced by supplying a conversion map. Characters outside the map are copied unchanged.
Typical uses are producing pure-ASCII output from Unicode text, or escaping a chosen set of characters for a channel that cannot carry raw multibyte bytes. The inverse operation is mb_decode_numericentity().
Signature
Parameters and defaults
$string: the text to convert.$map: a flat array of integers, read in groups of four:start,end,offset,mask. A character whose code point lies betweenstartandend(inclusive) is converted. PHP addsoffsetto the code point, applies a bitwise AND withmask, and writes the result as a numeric reference. Several groups can be placed one after another to describe several ranges.$encoding: the character encoding of$string. It defaults tonull, which means the current internal encoding. Passing"UTF-8"explicitly makes the call independent of configuration.$hex: defaults tofalse, giving decimal references likeあ. Withtrueyou get hexadecimal references likeあ.
Return value and failures
The function returns the converted string. It throws a ValueError if $map contains a value that is not an int, float, bool, null or numeric string. Since PHP 8.4.0 this check covers any value that cannot be implicitly converted to an int. A ValueError is also thrown when $encoding is not a valid encoding name, which has been the behavior since PHP 8.0.0. In PHP 8.0.0 the $encoding parameter also became nullable.
Example 1: encode everything above ASCII
A map covering code points from 0x80 upwards leaves ASCII alone and converts every other character. The mask 0x1FFFFF is wide enough not to alter any valid code point.
$map = [0x80, 0x10FFFF, 0, 0x1FFFFF];
echo json_encode(mb_encode_numericentity("caf\u{E9}", $map, "UTF-8"), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";"café"
The é (code point 233) becomes é, while caf is untouched.
Example 2: decimal and hexadecimal output
The fourth argument switches the notation. The character あ is U+3042, which is 12354 in decimal.
$map = [0x80, 0x10FFFF, 0, 0x1FFFFF];
$text = "a\u{3042}b";
echo json_encode([
mb_encode_numericentity($text, $map, "UTF-8"),
mb_encode_numericentity($text, $map, "UTF-8", true),
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";["aあb","aあb"]
Example 3: ranges and offsets
The map range selects characters, and the offset is added to each selected code point before the mask is applied. Here A, B and C (65 to 67) are shifted by 256, while D falls outside the range and is copied as is.
$map = [0x41, 0x43, 0x100, 0xFFFF];
echo json_encode(mb_encode_numericentity("ABCD", $map, "UTF-8"), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";"ŁłŃD"
The result is ŁłŃD. An offset of zero is the normal choice when you simply want the real code point. A non-zero offset only makes sense if the receiving side reverses it, for example with a matching mb_decode_numericentity() map.
Edge cases
- Ranges are inclusive. A group such as
0x3C, 0x3C, 0, 0xFFFFconverts only<. - Characters outside every range are never touched. An empty map therefore returns the string unchanged.
- The mask can corrupt code points. The AND operation is applied after the offset. If the mask has fewer bits than the code point needs, the high bits are dropped and the reference names a different character. The manual's example with mask
0x10FFFFshows this for a supplementary character: the printed number is smaller than the real code point. Use a mask such as0x1FFFFF(or0x10FFFFonly when you intend that truncation) after checking the result. - Hexadecimal digits. With
$hexset totrue, letters in the number may be uppercase or lowercase depending on the implementation, so do not compare hex output case-sensitively against hand-written text.
Common mistakes
- Writing the map as nested arrays. The map is one flat list; each rule is four consecutive integers, not a sub-array.
- Leaving out a value from a group. Every rule needs all four numbers. Keep complete groups of four.
- Putting non-numeric values in the map. Strings such as
"abc"cause aValueError. - Relying on the default encoding. If the internal encoding differs from your data, characters are interpreted incorrectly. Pass the encoding explicitly.
- Treating it as HTML escaping. It is not a replacement for
htmlspecialchars(). It only converts what your map selects. To escape<,>or&you must list them in the map yourself. - Forgetting to decode with a compatible map. If you used a non-zero offset, the decoding map must undo it.
Related functions
mb_decode_numericentity(): converts numeric references back to characters.htmlspecialchars()andhtmlentities(): escape HTML-significant characters using named entities.mb_convert_encoding(): converts text between character encodings, with an HTML-entities option.
Recap
Build a flat map of start, end, offset, mask groups, pass the encoding explicitly, and choose a mask wide enough for the code points involved. Use $hex to switch between é and é style output, and expect a ValueError for non-numeric map values or an invalid encoding.
Tested examples
$map = [0x80, 0x10FFFF, 0, 0x1FFFFF];
echo json_encode(mb_encode_numericentity("caf\u{E9}", $map, "UTF-8"), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
"café"
$map = [0x80, 0x10FFFF, 0, 0x1FFFFF];
$text = "a\u{3042}b";
echo json_encode([
mb_encode_numericentity($text, $map, "UTF-8"),
mb_encode_numericentity($text, $map, "UTF-8", true),
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
["aあb","aあb"]
$map = [0x41, 0x43, 0x100, 0xFFFF];
echo json_encode(mb_encode_numericentity("ABCD", $map, "UTF-8"), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
"ŁłŃD"