utf8_encode is deprecated and was never what you wanted

utf8_encode converts from ISO-8859-1 specifically, which is almost never the encoding the input was actually in.

// what people think it does: "make this UTF-8"
// what it does: assume Latin-1, and convert from that

utf8_encode("cafxC3xA9");   // already UTF-8 → "café"

// 8.2: Deprecated: Function utf8_encode() is deprecated

// the honest version, which requires knowing the source
mb_convert_encoding($s, 'UTF-8', 'ISO-8859-1');
mb_convert_encoding($s, 'UTF-8', 'Windows-1252');   // usually this

The double-encoding it produces is the single most common source of mojibake in PHP applications, and it happens because the function name promises a conversion to UTF-8 rather than a conversion from Latin-1. Windows-1252 is the encoding most legacy Western European data is actually in, and it differs from ISO-8859-1 in exactly the range that contains curly quotes and dashes — which is why the smart quotes are always the characters that break.