Spiega come Wordpress funziona con il set di caratteri MySQL e le regole di confronto a basso livello


10

Come suggerisce il titolo della domanda, sto cercando di capire come Wordpress funziona con i set di caratteri e le opzioni di confronto di MySQL. Come mostrerò di seguito, le cose non hanno molto senso per me ...

Ho installato Wordpress seguendo le istruzioni sulla loro pagina di installazione:

https://codex.wordpress.org/Installing_WordPress

Come parte delle istruzioni, ho seguito i loro consigli per la creazione manuale del database MySQL sulla riga di comando, in particolare i comandi:

mysql> CREATE DATABASE databasename;
Query OK, 1 row affected (0.00 sec)

mysql> GRANT ALL PRIVILEGES ON databasename.* TO "wordpressusername"@"hostname"
-> IDENTIFIED BY "password";
Query OK, 0 rows affected (0.00 sec)

mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.01 sec)

mysql> EXIT

Inoltre, come indicato, ho modificato il file "wp-config.php" per utilizzare il set di caratteri UTF-8:

define( 'DB_CHARSET', 'utf8' );

... e lasciato vuota l'impostazione di confronto:

define( 'DB_COLLATE', '' );

Qui è dove inizia il divertimento ...

  1. Se inserisco un personaggio che non fa parte di MySQL UTF-8, ma fa parte di UTF-8 MB4, come 𝌆, in un post, viene visualizzato correttamente nella pagina di rendering. Mi sarei aspettato che ciò non accadesse, poiché non ho impostato il set di caratteri su UTF-8 MB4, ma l'UTF-8 più limitato (come definito ovviamente da MySQL, non come generalmente capito).

  2. Se analizzo il problema in MySQL dalla riga di comando, diventa più strano. Se corro show variables like 'char%';, ottengo questa risposta:

    +--------------------------+----------------------------+
    | Variable_name            | Value                      |
    +--------------------------+----------------------------+
    | character_set_client     | utf8                       |
    | character_set_connection | utf8                       |
    | character_set_database   | latin1                     |
    | character_set_filesystem | binary                     |
    | character_set_results    | utf8                       |
    | character_set_server     | latin1                     |
    | character_set_system     | utf8                       |
    | character_sets_dir       | /usr/share/mysql/charsets/ |
    +--------------------------+----------------------------+
    

Mi sarei aspettato che il set di caratteri del database fosse UTF-8, non latino1.

  1. Se eseguo il comando show variables like 'collation%';, l'output è:

    +----------------------+-------------------+
    | Variable_name        | Value             |
    +----------------------+-------------------+
    | collation_connection | utf8_general_ci   |
    | collation_database   | latin1_swedish_ci |
    | collation_server     | latin1_swedish_ci |
    +----------------------+-------------------+
    

È ancora più strano, per ovvie ragioni (non si sarebbe aspettato il confronto latin1_swedish_ci predefinito in un database UTF-8).

  1. Infine, se corro show full columns from mywpdatabase.wp_posts;, le linee di output, dove il valore non è NULL, mostrano che le regole di confronto sono:

| post_content_filtered | longtext | utf8mb4_unicode_ci |

La mia domanda quindi: come può essere spiegato? Perché la mia installazione di Wordpress esegue correttamente il rendering dei caratteri UTF-8 MB4, quando il database è definito come UTF-8 nella configurazione? E perché il database mostra in MySQL come latin1, regole di confronto svedesi, anziché UTF-8? E come mai, nonostante tutto ciò, i singoli campi nella tabella sono utf8mb4_unicode_ci? Una spiegazione di basso livello sul modo in cui Wordpress funziona con MySQL sarebbe molto utile. Grazie!

Risposte:


11

Esistono due definizioni in wp-config.php del sito Web WordPress:

define('DB_CHARSET', 'utf8');
define('DB_COLLATE', '');

Ci sono molte cose che sono comunemente fraintese. I nomi delle costanti in tali definizioni potrebbero suggerire che sono correlati al database stesso. Non sono. Sono correlati alle tabelle all'interno del database.

La creazione del database è totalmente indipendente dalla creazione della tabella. WordPress non crea un database e non si preoccupa della serie di caratteri e delle regole di confronto predefinite del database, purché possa connettersi al database.

Il valore "utf8" nella prima definizione significa, il set di caratteri meno limitato dalla famiglia "utf8", che è "utf8" o "utf8mb4".

Se lasci le definizioni sopra invariate, prima di tentare di installare il tuo sito Web, è come dire a WordPress di fare le proprie scelte, per quanto riguarda il set di caratteri e le regole di confronto delle tabelle del database, che sono supportate da MySQL (a seconda della versione di MySQL) e sono meno limitanti.

Di seguito sono le cose, WordPress analizza per determinare le sue scelte, durante l'installazione:

  • Versione di MySQL
  • regole di confronto del database (in wp-config.php)

Basato sulla versione di MySQL, WordPress decide quale gruppo della famiglia utf8 utilizzare. Ce ne sono due, distinti dai loro nomi: utf8 e utf8mb4 . Set di caratteri dal gruppo utf8 , consentono la memorizzazione di caratteri lunghi al massimo 3 byte. Set di caratteri dal gruppo utf8mb4 , consentono la memorizzazione di caratteri lunghi al massimo 4 byte.

Ora, WordPress controlla il valore di DB_COLLATE define. Se vuoto, utilizzerà le regole di confronto meno limitanti della famiglia utf8 scelta , altrimenti utilizzerà il valore specificato.

Esempi

define('DB_CHARSET', 'utf8');
define('DB_COLLATE', '');

Se MySQL non supporta utf8mb4 (versioni precedenti), il set di caratteri delle tabelle sarà utf8 e le regole di confronto saranno utf8_general_ci . Altrimenti, possiamo aspettarci rispettivamente utf8mb4 e utf8mb4_unicode_520_ci o utf8mb4_unicode_ci (dipendente dalla versione di MySQL).

define('DB_CHARSET', 'utf8');
define('DB_COLLATE', 'utf8_polish_ci');

Vecchia versione di MySQL - utf8 e utf8_polish_ci . Versione MySQL più recente - utf8mb4 e utf8mb4_polish_ci (il suffisso _polish_ci è rispettato)

define('DB_CHARSET', 'cp1250');
define('DB_COLLATE', 'cp1250_polish_ci');

Qualsiasi versione di MySQL: cp1250 e cp1250_polish_ci .

define('DB_CHARSET', 'cp1250');
define('DB_COLLATE', 'utf8_general_ci');

Qualsiasi versione di MySQL - errore (mancata corrispondenza del set di caratteri e delle regole di confronto)

Sommario

Nella maggior parte dei casi, lasciare i valori di definisce, spiegato sopra, invariato, è una buona scelta. Ma, se si desidera che le regole di confronto delle tabelle corrispondano alla lingua del sito Web, è possibile modificare il valore di DB_COLLATE define, in modo appropriato (ad esempio - utf8mb4_polish_ci ).

Nota: questo spiega perché il personaggio 𝌆 è stato memorizzato e recuperato correttamente. Semplicemente, il set di caratteri delle tue tabelle apparteneva al gruppo utf8mb4 , non utf8 .


1
Grazie per aver spiegato come Wordpress imposta le regole di confronto, ma non hai affrontato il resto dei punti. Perché, se viene definito il set di caratteri UTF-8, MySQL mostra il database come latin1? E perché mostra le regole di confronto del database come svedesi? Inoltre, sembra che tu stia confondendo set di caratteri e regole di confronto. Le regole di confronto definiscono solo l'ordinamento, le regole di confronto, non il set di caratteri. Pertanto, indipendentemente dal tipo di regole di confronto utilizzate, se UTF-8 è il set di caratteri, i caratteri esterni (come definiti nel senso più stretto di MySQL) non devono essere visualizzati.
X-Mann,

Aggiornerò la mia risposta, per spiegare più chiaramente il processo.
Frank P. Walentynowicz,

1
Grazie per l'aggiornamento! Ho accettato la tua risposta, ora è tutto chiaro. Il problema è con MySQL e la mia mancanza di esperienza in esso - non sapevo che le tabelle possano usare un set di caratteri più ampio rispetto al database stesso. Questa nuova informazione mi ha messo a mio agio. Non ho bisogno di cambiare il set di caratteri predefinito in MySQL, Wordpress se ne occupa a livello di tabella.
X-Mann,

Prego. Sono contento che abbia aiutato.
Frank P. Walentynowicz,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.