Skip to Content

Chapitre 4.6 — La base de données & ses outils

⏱️ TL;DR — WordPress stocke tout son contenu dans une douzaine de tables MySQL. Les incontournables : wp_posts (articles, pages, médias, révisions, CPT…), wp_postmeta (leurs métadonnées), wp_options (réglages du site), wp_users/wp_usermeta, et le trio des taxonomies (terms, term_taxonomy, term_relationships). Savoir explorer cette base avec phpMyAdmin/Adminer (ou wp db query) démystifie WordPress. On y reviendra en profondeur (côté code, $wpdb) en Partie 5.

🎯 Objectifs

  • Connaître les tables clés et ce qu’elles contiennent.
  • Comprendre le modèle objet + méta (posts/postmeta, users/usermeta…).
  • Explorer la base avec un outil graphique et en CLI.
  • Repérer les pièges (préfixe, autoload des options).

1. Le schéma d’ensemble

Une installation standard compte ~12 tables (préfixées, wp_ par défaut) :

TableContient
wp_postsTous les contenus : articles, pages, médias (attachments), révisions, éléments de menu, et vos CPT. Une colonne post_type les distingue.
wp_postmetaMétadonnées clé/valeur rattachées à un post (post_id, meta_key, meta_value).
wp_optionsRéglages globaux du site (titre, URL, options de plugins/thèmes).
wp_users / wp_usermetaComptes + leurs métadonnées (dont rôles/capabilities).
wp_terms, wp_term_taxonomy, wp_term_relationshipsLe système de taxonomies (catégories, étiquettes, taxonomies custom) et leur liaison aux contenus.
wp_comments / wp_commentmetaCommentaires.

2. Le modèle « objet + table de méta »

Un schéma récurrent : un objet (post, user, comment, term) a une table principale + une table de métadonnées clé/valeur. Cela rend le modèle extensible sans migration : ajouter une donnée à un article, c’est insérer une ligne dans wp_postmeta (meta_key = 'prix', meta_value = '19.90'), pas modifier le schéma.

wp_posts (ID=42, post_title="T-shirt", post_type="product") └── wp_postmeta (post_id=42, meta_key="_prix", meta_value="19.90") wp_postmeta (post_id=42, meta_key="_stock", meta_value="12")

💡 Pour un dev React — C’est un modèle EAV (Entity-Attribute-Value) : très flexible (on ajoute des champs sans toucher au schéma), au prix de la performance sur les requêtes complexes (jointures sur meta). En développement, vous lirez/écrirez ces métadonnées via des fonctions dédiées — get_post_meta(), update_post_meta() (Partie 7) — sans SQL brut. C’est l’équivalent d’un « champ JSON extensible » attaché à chaque entité, mais stocké en lignes.


3. La table wp_options (et le piège autoload)

wp_options stocke les réglages sous forme clé/valeur (option_name, option_value, autoload). La colonne autoload est cruciale : les options en autoload = yes sont toutes chargées à chaque requête (en une seule requête, mises en cache mémoire).

⚠️ Piège — l’autoload qui gonfle. Des plugins mal écrits stockent de grosses données en option autoloadée, chargées à chaque page → mémoire et temps gaspillés. Un wp_options de plusieurs Mo autoloadés est une cause classique de lenteur. On l’audite (wp option list --autoload=on --format=count, requêtes sur la taille) en Partie 11. Retenez : une option volumineuse ou rarement lue ne doit pas être autoloadée.


4. Explorer la base

  • Outils graphiques : phpMyAdmin, Adminer (souvent fourni par l’env local), ou un client SQL (TablePlus, DBeaver). On y parcourt les tables, on lance des requêtes, on exporte.
  • En CLI : wp db query "SELECT ID, post_title FROM wp_posts WHERE post_type='page'", ou wp db cli pour un shell MySQL. wp db export pour un dump.
  • Quelques requêtes utiles :
-- Compter les contenus par type SELECT post_type, COUNT(*) FROM wp_posts GROUP BY post_type; -- Les options autoloadées les plus lourdes SELECT option_name, LENGTH(option_value) AS taille FROM wp_options WHERE autoload='yes' ORDER BY taille DESC LIMIT 10;

⚠️ Piège — le préfixe. N’écrivez jamais wp_ en dur : le préfixe de tables peut différer d’un site à l’autre (wp_, wp_a1b2_…). En SQL brut d’exploration, c’est acceptable localement, mais dans du code vous utiliserez toujours $wpdb->posts, $wpdb->prefix (Partie 5), jamais un nom de table en dur.


5. Ne pas écrire de SQL brut… en général

Explorer la base à la main est formateur, mais en code, on passe par les API de WordPress (WP_Query, get_posts(), get_post_meta(), get_option() — Parties 5 et 7). Elles gèrent le préfixe, la sécurité (requêtes préparées), le cache et la compatibilité. Le SQL direct ($wpdb->get_results()) est réservé aux cas que les API ne couvrent pas — toujours préparé ($wpdb->prepare()), jamais concaténé (Partie 7 : sécurité).


✏️ Exercices

  1. Dans quelle table trouve-t-on un article, une page, une image et un produit WooCommerce ? Qu’est-ce qui les distingue ?
  2. Expliquez le modèle « objet + méta » et son avantage principal.
  3. Pourquoi une option volumineuse en autoload=yes peut-elle ralentir tout le site ?

✅ Solution

  1. Tous dans wp_posts ; la colonne post_type les distingue (post, page, attachment, product). WordPress unifie les contenus dans une même table, typée par post_type.
  2. Un objet (post) a une table principale (wp_posts) + une table de métadonnées clé/valeur (wp_postmeta). Avantage : on ajoute des données sans modifier le schéma (flexibilité, extensibilité).
  3. Parce que toutes les options autoload=yes sont chargées à chaque requête ; une option volumineuse gonfle la mémoire et le temps de chaque page, même si elle n’est presque jamais utilisée.

🧠 Quiz de révision

1. Quelle table contient articles, pages, médias et CPT ?

wp_posts, la colonne post_type distinguant les types.

2. Où sont stockées les métadonnées d’un article ?

Dans wp_postmeta (paires clé/valeur reliées par post_id).

3. Quelles tables gèrent les taxonomies ?

wp_terms, wp_term_taxonomy et wp_term_relationships.

4. Que fait la colonne autoload de wp_options ?

Elle indique si l’option est chargée automatiquement à chaque requête ; mal utilisée, elle dégrade la performance.

5. En code, comment référence-t-on une table sans coder le préfixe en dur ?

Via $wpdb : $wpdb->posts, $wpdb->prefix, etc. (Partie 5).


Partie suivante : Partie 5 — Architecture du cœur de WordPress.