Skip to content

fix(eloquent): talk to MySQL the way WordPress does - #115

Merged
gfazioli merged 1 commit into
masterfrom
fix/eloquent-mysql-connection
Sep 25, 2026
Merged

gfazioli merged 1 commit into
masterfrom
fix/eloquent-mysql-connection

Conversation

@gfazioli

Copy link
Copy Markdown
Collaborator

Follow-up to #113, found while fixing #110.

The problem

The MySQL connection hard-coded utf8 / utf8_unicode_ci and passed DB_HOST as the host. Measured on a local site: MySQL 8.4, tables utf8mb4_unicode_520_ci, DB_CHARSET 'utf8' (which WordPress raises to utf8mb4 itself), and a sql_mode without STRICT_*.

  • Writing an emoji through Eloquent failed: SQLSTATE[HY000]: General error: 3988 Conversion from collation utf8mb3_unicode_ci into utf8mb4_unicode_520_ci impossible for parameter.
  • An emoji written by WordPress came back through Eloquent as emoji ? ok.
  • DB_HOST localhost:/tmp/mysql.sock did not connect: SQLSTATE[HY000] [2002] Can't assign requested address. host:port already worked, because PDO accepts it.

The fix

The connection now follows WordPress's own:

  • charset and collation: $wpdb->charset and $wpdb->collate, what WordPress actually uses on its connection. Not DB_CHARSET, which here says utf8. An empty collation is left out instead of being sent as collate ''.
  • host: DB_HOST goes through $wpdb->parse_db_host(), as in wpdb::db_connect(). That gives Laravel a port, a unix_socket, and an IPv6 host in brackets when mysqlnd is loaded.
  • Without $wpdb: the host is passed as it is and the charset is utf8mb4.

SQLite (#113) is unchanged.

Tests

  • tests/Unit/EloquentTest.php has 10 tests, 6 of them new. A stand-in $wpdb answers parse_db_host() the way WordPress does, and the tests check how that answer becomes Laravel's connection: charset and collation, port, socket, IPv6 brackets, empty collation, an unparsable host, no $wpdb. The full suite passes: 158 tests.
  • Live, eloquent-live-smoke.sh in the workspace, in the bench (MySQL) and in a local @wp-playground/cli (SQLite):
Check v2.0.11 this branch
MySQL: connection charset/collation = WordPress's (utf8mb4, utf8mb4_unicode_520_ci) ✗ utf8 / utf8_unicode_ci ✓
MySQL: an emoji written by Eloquent reaches the table intact ✗ error 3988 ✓
MySQL: an emoji written by WordPress is read back intact by Eloquent ✗ emoji ? ok ✓
MySQL: DB_HOST localhost, localhost:3306, 127.0.0.1:3306 connect ✓ ✓
MySQL: DB_HOST localhost:/tmp/mysql.sock connects ✗ ✓
SQLite: the Database demo's 11 Eloquent examples ✓ ✓

The IPv6 form isn't in the live run: this MySQL listens on 127.0.0.1 only, and mysqli refuses [::1] too. The brackets are covered by the unit test, which mirrors wpdb::db_connect().

The MySQL connection hard-coded utf8 / utf8_unicode_ci and passed DB_HOST
as the host. Measured on wpbones.test (MySQL 8.4, tables utf8mb4, DB_CHARSET
'utf8' that WordPress raises to utf8mb4):

- writing an emoji through Eloquent failed with error 3988, "Conversion
  from collation utf8mb3_unicode_ci into utf8mb4_unicode_520_ci impossible";
- an emoji written by WordPress came back through Eloquent as "?";
- DB_HOST 'localhost:/tmp/mysql.sock' did not connect ("Can't assign
  requested address"). host:port already did: PDO accepts it.

The charset and collation are now the ones WordPress settled on
($wpdb->charset, $wpdb->collate; an empty collation is left out rather than
sent as `collate ''`), and DB_HOST goes through $wpdb->parse_db_host() as in
wpdb::db_connect(): port, unix socket, and an IPv6 host bracketed for
mysqlnd. Without $wpdb the host is passed as it is and the charset is
utf8mb4.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟢 Approval recommended

No unresolved blocking issues were identified.

Review effort: Lite
Findings: None

What changed in this PR

Updates Eloquent’s MySQL connection to match WordPress’s charset, collation, and host parsing while preserving SQLite support.

Changes:

  • Uses $wpdb settings with an utf8mb4 fallback.
  • Supports ports, Unix sockets, and IPv6 hosts.
  • Adds unit coverage for MySQL configuration variants.
File Description
tests/​Unit/​EloquentTest.php Tests charset, collation, host parsing, and fallback behavior.
src/​Database/​Eloquent.php Implements WordPress-compatible MySQL connection settings.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@gfazioli
gfazioli merged commit 4f4256b into master Sep 25, 2026
5 checks passed
@gfazioli
gfazioli deleted the fix/eloquent-mysql-connection branch September 25, 2026 09:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants