TL;DR — Destoon's database driver compares the MySQL server version as a string instead of a version number. On MariaDB 10.x, "10.6.27-MariaDB" > "4.1" evaluates to false, so SET NAMES 'utf8' is silently skipped, the connection stays on latin1, and every Chinese character collapses into a single ?. The fix is a one-liner: use version_compare().
The symptom
After migrating a Destoon site to a server running MariaDB 10.x (the default database for DirectAdmin, cPanel, 宝塔/BT, and most LNMP stacks), the entire site's Chinese text turned into ????:
- The homepage showed 78 places of
???? - Member shop
<title>tags broke - The admin sidebar became all
?
Meanwhile the same site on MySQL 5.7 was completely fine. No template changes, no PHP-version issue, no data corruption.
The debugging path (the part that matters)
We first ruled out the usual suspects, because none of them were the cause:
- Data intact — a
HEX()dump showed the bytes were correct in storage. - Templates fine — the compiled template cache was logically correct.
- Connection layer — a minimal probe that replicated Destoon's exact connection path printed
conn_charset_now=latin1andSET NAMES SKIPPED. That was the smoking gun.
The root cause
In module/destoon/db_mysqli.class.php, Destoon decides whether to set the connection charset by comparing the server version as a string:
$version = mysqli_get_server_info($this->connid);
if($version > '4.1' && $this->cfg['db_charset']) {
mysqli_query($this->connid, "SET NAMES '".$this->cfg['db_charset']."'");
}
if($version > '5.0') {
mysqli_query($this->connid, "SET SQL_MODE=''");
}
PHP string comparison is lexicographic (character by character, by ASCII value):
- MariaDB 10.x returns
10.6.27-MariaDB. Comparing against'4.1': first characters'1'vs'4'—'1'<'4'— the whole string is "less than"4.1—false. - So
SET NAMES 'utf8'never runs. The connection stays on the server defaultlatin1. - MySQL 5.7 returns
5.7.26.'5' > '4'—true—SET NAMESruns — Chinese is fine.
That single false on every MariaDB 10.x box is why a "works in dev, breaks in production" mystery happens: your dev box is MySQL 5.x, your production box is MariaDB 10.x.
The fix
Replace string comparison with numeric version comparison:
$version = mysqli_get_server_info($this->connid);
if(version_compare($version, '4.1', '>') && $this->cfg['db_charset']) {
mysqli_query($this->connid, "SET NAMES '".$this->cfg['db_charset']."'");
}
if(version_compare($version, '5.0', '>')) {
mysqli_query($this->connid, "SET SQL_MODE=''");
}
version_compare('10.6.27-MariaDB', '4.1', '>') correctly parses 10.6 and returns true.
The result
- Homepage
????: 78 — 0 - Member shop
<title>restored to correct Chinese - Admin sidebar cleared
Why this matters to you
MariaDB 10.x is the default on nearly every shared/VPS control panel. If you run Destoon on MariaDB — or are about to migrate to a host that ships it — you will hit this, regardless of PHP version. Check your db_mysqli.class.php now.
