Cum funcționează WordPress cu setul de caractere și colația MySQL la nivel scăzut?

13 mai 2017, 20:58:05
Vizualizări: 14.3K
Voturi: 16

După cum sugerează titlul întrebării, încerc să înțeleg cum funcționează WordPress cu seturile de caractere și opțiunile de colație MySQL. După cum voi arăta mai jos, lucrurile nu prea au sens pentru mine...

Am instalat WordPress urmând instrucțiunile de pe pagina lor de instalare:

https://codex.wordpress.org/Installing_WordPress

Ca parte a instrucțiunilor, am urmat sfatul lor pentru crearea manuală a bazei de date MySQL în linia de comandă, și anume comenzile:

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

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

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

mysql> EXIT

Mai departe, așa cum am fost instruit, am editat fișierul "wp-config.php" să folosească setul de caractere UTF-8:

define( 'DB_CHARSET', 'utf8' );

...și am lăsat setarea de colație goală:

define( 'DB_COLLATE', '' );

Aici începe distracția...

  1. Dacă introduc un caracter care nu face parte din UTF-8 MySQL, dar face parte din UTF-8 MB4, cum ar fi , într-un post, acesta apare corect pe pagina randată. M-aș fi așteptat ca acest lucru să nu se întâmple, deoarece nu am setat setul de caractere la UTF-8 MB4, ci la UTF-8 mai restrâns (așa cum este definit de MySQL, desigur, nu ca în înțelesul general).

  2. Dacă investighez problema în MySQL în linia de comandă, devine și mai ciudat. Dacă rulez show variables like 'char%';, primesc acest răspuns:

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

M-aș fi așteptat ca setul de caractere al bazei de date să fie UTF-8, nu latin1.

  1. Dacă rulez comanda show variables like 'collation%';, rezultatul este:

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

Acest lucru este și mai ciudat, din motive evidente (nu m-aș fi așteptat la colația implicită latin1_swedish_ci într-o bază de date UTF-8).

  1. În final, dacă rulez show full columns from mywpdatabase.wp_posts;, liniile de rezultat, unde valoarea nu este NULL, arată colația ca fiind:

| post_content_filtered | longtext | utf8mb4_unicode_ci |

Întrebarea mea este atunci - cum poate fi explicat acest lucru? De ce instalarea mea de WordPress afișează corect caracterele UTF-8 MB4, când baza de date este definită ca UTF-8 în configurație? Și de ce baza de date apare în MySQL ca latin1, cu colație suedeză, în loc de UTF-8? Și cum se face că, în ciuda tuturor acestora, câmpurile individuale din tabel sunt utf8mb4_unicode_ci? O explicație la nivel scăzut despre modul în care funcționează WordPress cu MySQL ar fi foarte utilă. Mulțumesc!

0
Toate răspunsurile la întrebare 1
4
16

Există două definiții în wp-config.php ale unui site WordPress:

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

Sunt mai multe lucruri care sunt adesea înțelese greșit. Numele constantelor din aceste definiții ar putea sugera că sunt legate de baza de date în sine. Ele nu sunt. Ele sunt legate de tabelele din baza de date.

Crearea bazei de date este total independentă de crearea tabelelor. WordPress nu creează o bază de date și nu are grijă de setul de caractere implicit și colația bazei de date, atâta timp cât se poate conecta la aceasta.

Valoarea 'utf8' din prima definiție înseamnă cel mai puțin restrictiv set de caractere din familia 'utf8', care este fie 'utf8', fie 'utf8mb4'.

Dacă lăsați definițiile de mai sus neschimbate, înainte de a încerca să instalați site-ul, este ca și cum ați spune WordPress să facă propriile alegeri, cu privire la setul de caractere și colația tabelelor bazei de date, care sunt suportate de MySQL (în funcție de versiunea MySQL) și sunt cele mai puțin restrictive.

Următoarele sunt lucrurile pe care WordPress le analizează pentru a determina alegerile sale, în timpul instalării:

  • Versiunea MySQL
  • Colația bazei de date (în wp-config.php)

Pe baza versiunii MySQL, WordPress decide care grup din familia utf8 să utilizeze. Există două, distinse prin numele lor: utf8 și utf8mb4. Seturile de caractere din grupul utf8 permit stocarea caracterelor cu o lungime maximă de 3 octeți. Seturile de caractere din grupul utf8mb4 permit stocarea caracterelor cu o lungime maximă de 4 octeți.

Acum, WordPress verifică valoarea definiției DB_COLLATE. Dacă este goală, va utiliza colația cea mai puțin restrictivă din familia utf8 aleasă, altfel, va utiliza valoarea specificată.

Exemple

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

Dacă MySQL nu suportă utf8mb4 (versiuni mai vechi) atunci setul de caractere al tabelelor va fi utf8 și colația va fi utf8_general_ci. Altfel, ne putem aștepta la utf8mb4 și utf8mb4_unicode_520_ci, sau utf8mb4_unicode_ci (în funcție de versiunea MySQL), respectiv.

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

Versiune mai veche a MySQL - utf8 și utf8_polish_ci. Versiune mai nouă a MySQL - utf8mb4 și utf8mb4_polish_ci (sufixul _polish_ci este respectat)

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

Orice versiune MySQL - cp1250 și cp1250_polish_ci.

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

Orice versiune MySQL - eroare (neconcordanță între setul de caractere și colație)

Rezumat

În majoritatea cazurilor, lăsarea valorilor definițiilor, explicate mai sus, neschimbate, este o alegere bună. Dar, dacă doriți ca colația tabelelor să se potrivească cu limba site-ului dvs., puteți modifica valoarea definiției DB_COLLATE, în mod corespunzător (de exemplu - utf8mb4_polish_ci).

Notă: asta explică de ce caracterul a fost stocat și recuperat corect. Pur și simplu, setul de caractere al tabelelor dvs. a aparținut grupului utf8mb4, nu utf8.

14 mai 2017 08:48:14
Comentarii

Mulțumesc pentru explicația despre cum WordPress setează colația, dar nu ai abordat restul punctelor. De ce, dacă setul de caractere UTF-8 este definit, MySQL afișează baza de date ca fiind latin1? Și de ce arată colația bazei de date ca fiind swedish? În plus, se pare că confunzi setul de caractere cu colația. Colația definește doar regulile de ordonare și comparare, nu setul de caractere. Prin urmare, indiferent de colația folosită, dacă UTF-8 este setul de caractere, caracterele din afara acestuia (așa cum sunt definite în sensul mai restrâns al MySQL) nu ar trebui să fie redate.

X-Mann X-Mann
14 mai 2017 14:54:34

Voi actualiza răspunsul meu, pentru a explica mai clar procesul.

Frank P. Walentynowicz Frank P. Walentynowicz
14 mai 2017 19:07:38

Mulțumesc pentru actualizare! Am acceptat răspunsul tău, acum totul este clar. Problema este cu MySQL și lipsa mea de expertiză în acest domeniu - nu știam că tabelele pot folosi un set de caractere mai larg decât baza de date în sine. Această informație nouă m-a liniștit. Nu trebuie să schimb setul de caractere implicit în MySQL, WordPress se ocupă de asta la nivel de tabel.

X-Mann X-Mann
15 mai 2017 11:04:41

Cu plăcere. Mă bucur că ți-a fost de ajutor.

Frank P. Walentynowicz Frank P. Walentynowicz
15 mai 2017 12:11:16