Short description
$config->dbCharset is applied to the DB connection only via the default
$config->dbInitCommand (SET NAMES '{charset}'). Overriding dbInitCommand
— e.g. the common SET time_zone = '...' recipe — silently drops the charset,
so the connection falls back to the MySQL server default with no warning. On a
latin1-default server this silently double-encodes all edited content (UTF-8
stored through a latin1 connection), typically discovered days later.
Reproduce
- Set
$config->dbInitCommand = "SET time_zone = '-04:00'"; (no SET NAMES).
- On a server whose default charset is latin1, edit any page with accented
text / smart quotes.
- Content is now double-encoded at rest; no notice anywhere.
Root cause (WireDatabasePDO::getInstance)
- charset is only injected into
MYSQL_ATTR_INIT_COMMAND; the DSN
(socket/name/host/port) carries no charset= parameter.
- So
dbCharset depends entirely on dbInitCommand containing SET NAMES.
Proposed
- Prevent: also set the charset in the PDO DSN (
;charset={$charset}), or
apply SET NAMES independently of the user-overridable dbInitCommand, so
the charset survives an override.
- Warn (defense in depth): after connect, if the session
character_set_connection doesn't match $config->dbCharset, add a
superuser admin notice — mirroring the existing DB-time-vs-PHP-time warning.
(Cheap: one @@character_set_connection read, gated to admin/superuser.)
Why it matters
dbInitCommand is a documented, commonly-overridden setting, and the failure
is silent, data-corrupting, and hard to diagnose after the fact.
Note:
I built a small diagnostics module that confirms the mismatch is reliably detectable at runtime; Likely to be released soon, it can detect these types of issues and repair double and triple encoded and do a lot more; but i think during the development of the module came to the conclusion that it would be nice for the core to be protected from someone inadvertently overriding the connection charset - something that i've seen in the forums and is risky for certain hosting environments (as happened to 2 sites i worked on).
Short description
$config->dbCharsetis applied to the DB connection only via the default$config->dbInitCommand(SET NAMES '{charset}'). OverridingdbInitCommand— e.g. the common
SET time_zone = '...'recipe — silently drops the charset,so the connection falls back to the MySQL server default with no warning. On a
latin1-default server this silently double-encodes all edited content (UTF-8
stored through a latin1 connection), typically discovered days later.
Reproduce
$config->dbInitCommand = "SET time_zone = '-04:00'";(no SET NAMES).text / smart quotes.
Root cause (WireDatabasePDO::getInstance)
MYSQL_ATTR_INIT_COMMAND; the DSN(socket/name/host/port) carries no
charset=parameter.dbCharsetdepends entirely ondbInitCommandcontainingSET NAMES.Proposed
;charset={$charset}), orapply
SET NAMESindependently of the user-overridabledbInitCommand, sothe charset survives an override.
character_set_connectiondoesn't match$config->dbCharset, add asuperuser admin notice — mirroring the existing DB-time-vs-PHP-time warning.
(Cheap: one
@@character_set_connectionread, gated to admin/superuser.)Why it matters
dbInitCommandis a documented, commonly-overridden setting, and the failureis silent, data-corrupting, and hard to diagnose after the fact.
Note:
I built a small diagnostics module that confirms the mismatch is reliably detectable at runtime; Likely to be released soon, it can detect these types of issues and repair double and triple encoded and do a lot more; but i think during the development of the module came to the conclusion that it would be nice for the core to be protected from someone inadvertently overriding the connection charset - something that i've seen in the forums and is risky for certain hosting environments (as happened to 2 sites i worked on).