Veuillez expliquer comment Wordpress fonctionne avec le jeu de caractères et le classement MySQL à un bas niveau

10

Comme le titre de la question le suggère, je cherche à comprendre comment Wordpress fonctionne avec les jeux de caractères MySQL et les options de classement. Comme je vais le montrer ci-dessous, les choses n'ont pas beaucoup de sens pour moi ...

J'ai installé Wordpress en suivant les instructions sur leur page d'installation:

https://codex.wordpress.org/Installing_WordPress

Dans le cadre des instructions, j'ai suivi leurs conseils pour la création manuelle de la base de données MySQL sur la ligne de commande, à savoir les commandes:

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

De plus, comme indiqué, j'ai édité le fichier "wp-config.php" pour utiliser le jeu de caractères UTF-8:

define( 'DB_CHARSET', 'utf8' );

... et laissé le paramètre d'assemblage vide:

define( 'DB_COLLATE', '' );

Voici où le plaisir commence ...

  1. Si j'entre un caractère qui ne fait pas partie de MySQL UTF-8, mais qui fait partie de UTF-8 MB4, comme 𝌆, dans un message, il apparaît correctement sur la page rendue. Je m'attendais à ce que cela ne se produise pas, car je n'ai pas défini le jeu de caractères sur UTF-8 MB4, mais l'UTF-8 plus restreint (tel que défini par MySQL bien sûr, pas comme généralement compris).

  2. Si j'examine le problème dans MySQL sur la ligne de commande, cela devient plus étrange. Si je cours show variables like 'char%';, j'obtiens cette réponse:

    +--------------------------+----------------------------+
    | 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/ |
    +--------------------------+----------------------------+

Je m'attendais à ce que le jeu de caractères de la base de données soit UTF-8, pas latin1.

  1. Si j'exécute la commande show variables like 'collation%';, la sortie est:

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

C'est encore plus étrange, pour des raisons évidentes (je ne m'attendais pas au classement latin1_swedish_ci par défaut dans une base de données UTF-8).

  1. Enfin, si je lance show full columns from mywpdatabase.wp_posts;, les lignes de sortie, où la valeur n'est pas NULL, montrent que le classement est:

| post_content_filtered | longtext | utf8mb4_unicode_ci |

Ma question alors - comment expliquer cela? Pourquoi mon installation Wordpress affiche-t-elle correctement les caractères UTF-8 MB4, alors que la base de données est définie comme UTF-8 dans la configuration? Et pourquoi la base de données s'affiche-t-elle dans MySQL comme latin1, collation suédoise, au lieu de UTF-8? Et comment se fait-il que, malgré tout cela, les champs individuels de la table soient utf8mb4_unicode_ci? Une explication de bas niveau du fonctionnement de Wordpress avec MySQL serait très utile. Je vous remercie!

X-Mann
la source

Réponses:

11

Il existe deux définitions dans wp-config.php du site Web WordPress:

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

Il y a plusieurs choses qui sont le plus souvent mal comprises. Les noms des constantes dans ces définitions peuvent suggérer qu'elles sont liées à la base de données elle-même. Ils ne sont pas. Ils sont liés aux tables de la base de données.

La création de base de données est totalement indépendante de la création de table. WordPress ne crée pas de base de données et ne se soucie pas du jeu de caractères et du classement par défaut de la base de données, tant qu'il peut se connecter à la base de données.

La valeur «utf8» dans la première définition signifie, le jeu de caractères le moins restreint de la famille «utf8», qui est «utf8» ou «utf8mb4».

Si vous laissez les définitions ci-dessus inchangées, avant d'essayer d'installer votre site Web, c'est comme dire à WordPress de faire ses propres choix, en ce qui concerne le jeu de caractères et le classement des tables de la base de données, qui sont pris en charge par MySQL (selon la version de MySQL) et sont les moins limitatifs.

Voici les choses que WordPress analyse pour déterminer ses choix lors de l'installation:

  • Version de MySQL
  • classement de la base de données (dans wp-config.php)

Basé sur la version de MySQL, WordPress décide quel groupe de la famille utf8 utiliser. Il y en a deux, distingués par leurs noms: utf8 et utf8mb4 . Les jeux de caractères du groupe utf8 permettent de stocker un maximum de 3 octets de long caractères. Les jeux de caractères du groupe utf8mb4 permettent de stocker un maximum de 4 caractères longs.

Maintenant, WordPress vérifie la valeur de DB_COLLATE define. S'il est vide, il utilisera le classement le moins limitatif de la famille utf8 choisie , sinon, il utilisera la valeur spécifiée.

Exemples

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

Si MySQL ne prend pas en charge utf8mb4 (anciennes versions), le jeu de caractères des tables sera utf8 et le classement sera utf8_general_ci . Sinon, nous pouvons nous attendre à utf8mb4 et utf8mb4_unicode_520_ci , ou utf8mb4_unicode_ci (selon la version de MySQL), respectivement.

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

Ancienne version de MySQL - utf8 et utf8_polish_ci . Version MySQL plus récente - utf8mb4 et utf8mb4_polish_ci (le suffixe _polish_ci est respecté )

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

Toute version de MySQL - cp1250 et cp1250_polish_ci .

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

Toute version de MySQL - erreur (incompatibilité du jeu de caractères et du classement)

Résumé

Dans la plupart des cas, laisser les valeurs de define, expliquées ci-dessus, inchangées, est un bon choix. Mais, si vous souhaitez que le classement des tableaux corresponde à la langue de votre site Web, vous pouvez modifier la valeur de DB_COLLATE define, de manière appropriée (par exemple - utf8mb4_polish_ci ).

Remarque: cela explique pourquoi le caractère 𝌆 a été stocké et récupéré correctement. Simplement, votre jeu de caractères de tables appartenait au groupe utf8mb4 , pas à utf8 .

Frank P. Walentynowicz
la source
1
Merci d'avoir expliqué comment Wordpress définit le classement, mais vous n'avez pas abordé le reste des points. Pourquoi, si le jeu de caractères UTF-8 est défini, MySQL montre-t-il que la base de données est latin1? Et pourquoi montre-t-il que le classement des bases de données est suédois? De plus, vous semblez confondre jeu de caractères et collation. Le classement définit uniquement l'ordre, les règles de comparaison, pas le jeu de caractères. Par conséquent, quel que soit le classement utilisé, si UTF-8 est le jeu de caractères, les caractères en dehors de celui-ci (tels que définis au sens étroit de MySQL) ne doivent pas être rendus.
X-Mann
Je mettrai à jour ma réponse, pour expliquer plus clairement le processus.
Frank P. Walentynowicz
1
Merci pour la mise à jour! J'ai accepté votre réponse, tout est clair maintenant. Le problème est avec MySQL et mon manque d'expertise dans ce domaine - je ne savais pas que les tables peuvent utiliser un jeu de caractères plus large que la base de données elle-même. Cette nouvelle information m'a rassuré. Je n'ai pas besoin de changer le jeu de caractères par défaut dans MySQL, Wordpress s'en charge au niveau de la table.
X-Mann
Je vous en prie. Je suis content que cela ait aidé.
Frank P. Walentynowicz