Skip to content

Exercices - Taxonomies

This content is not available in your language yet.

Créer un nouveau vocabulaire “Collection” pour regrouper les produits par saison.

  1. Créez le vocabulaire Collection (collection)
  2. Ajoutez les termes suivants :
    • Printemps/Été 2025
    • Automne/Hiver 2024
    • Capsule Limitée
    • Classiques
  3. Ajoutez un champ Date de fin (type Date) au vocabulaire
  4. Créez le champ de référence field_collection dans le type Product
  5. Configurez le widget et le formatter
💡 Solution
// Via Drush
drush ev "
// Créer le vocabulaire
\Drupal\taxonomy\Entity\Vocabulary::create([
'vid' => 'collection',
'name' => 'Collection',
'description' => 'Collections saisonnières',
])->save();
echo \"Vocabulaire créé\n\";
// Créer les termes
\$terms = [
'Printemps/Été 2025',
'Automne/Hiver 2024',
'Capsule Limitée',
'Classiques',
];
foreach (\$terms as \$name) {
\Drupal\taxonomy\Entity\Term::create([
'vid' => 'collection',
'name' => \$name,
])->save();
echo \"Terme créé: \$name\n\";
}
"

Pour le champ Date :

  1. StructureTaxonomyCollectionManage fields
  2. Add fieldDatefield_end_date
  3. Widget : Date et heure

Pour le champ de référence dans Product :

  1. StructureContent typesProductManage fields
  2. Add fieldReferenceTaxonomy term
  3. Configurer : field_collection, lié à “Collection”

Transformer le vocabulaire “Catégorie Produit” en structure hiérarchique.

Réorganisez les termes ainsi :

Catégorie Produit
├── Hommes
│ ├── T-shirts Hommes
│ ├── Pantalons Hommes
│ └── Sweats Hommes
├── Femmes
│ ├── Robes
│ ├── Jupes
│ └── Blouses
├── Accessoires
│ ├── Sacs
│ ├── Bijoux
│ └── Lunettes
└── Chaussures
├── Sneakers
└── Bottes
  1. Comment créer un terme enfant dans l’interface ?
  2. Comment accéder au terme parent en PHP ?
  3. Comment afficher tous les enfants d’un terme ?
💡 Solutions

1. Créer un terme enfant :

  • Éditez un terme existant
  • Dans RelationsParent terms, sélectionnez le parent
  • Ou lors de la création, indiquez le parent

2. Accéder au parent en PHP :

$term = \Drupal::entityTypeManager()
->getStorage('taxonomy_term')
->load($tid);
// Récupérer les parents
$parents = \Drupal::entityTypeManager()
->getStorage('taxonomy_term')
->loadParents($term->id());
foreach ($parents as $parent) {
echo $parent->label();
}

3. Afficher les enfants :

$children = \Drupal::entityTypeManager()
->getStorage('taxonomy_term')
->loadChildren($parent_tid);
foreach ($children as $child) {
echo $child->label();
}
// Ou récursivement (tous les descendants)
$tree = \Drupal::entityTypeManager()
->getStorage('taxonomy_term')
->loadTree('product_category', $parent_tid);

Écrire des requêtes pour filtrer les produits par taxonomie.

Écrivez les requêtes pour :

  1. Trouver tous les produits Nike de couleur Noir
  2. Compter les produits par catégorie
  3. Trouver les produits disponibles en taille L ET XL
💡 Solution 1 : Produits Nike noirs
<?php
// Récupérer les TIDs
$brand_tid = \Drupal::entityTypeManager()
->getStorage('taxonomy_term')
->getQuery()
->accessCheck(FALSE)
->condition('vid', 'brand')
->condition('name', 'Nike')
->execute();
$brand_tid = reset($brand_tid);
$color_tid = \Drupal::entityTypeManager()
->getStorage('taxonomy_term')
->getQuery()
->accessCheck(FALSE)
->condition('vid', 'color')
->condition('name', 'Noir')
->execute();
$color_tid = reset($color_tid);
// Requête sur les produits
$nids = \Drupal::entityTypeManager()
->getStorage('node')
->getQuery()
->accessCheck(TRUE)
->condition('type', 'product')
->condition('status', 1)
->condition('field_brand', $brand_tid)
->condition('field_colors', $color_tid)
->execute();
$products = \Drupal::entityTypeManager()
->getStorage('node')
->loadMultiple($nids);
foreach ($products as $product) {
echo $product->label() . "\n";
}
💡 Solution 2 : Compter par catégorie
<?php
// Charger tous les termes de catégorie
$categories = \Drupal::entityTypeManager()
->getStorage('taxonomy_term')
->loadByProperties(['vid' => 'product_category']);
foreach ($categories as $category) {
$count = \Drupal::entityTypeManager()
->getStorage('node')
->getQuery()
->accessCheck(TRUE)
->condition('type', 'product')
->condition('status', 1)
->condition('field_category', $category->id())
->count()
->execute();
echo $category->label() . ': ' . $count . " produits\n";
}
💡 Solution 3 : Produits avec L ET XL
<?php
// Récupérer les TIDs des tailles
$sizes = \Drupal::entityTypeManager()
->getStorage('taxonomy_term')
->getQuery()
->accessCheck(FALSE)
->condition('vid', 'size')
->condition('name', ['L', 'XL'], 'IN')
->execute();
// Requête avec plusieurs conditions sur le même champ
$query = \Drupal::entityTypeManager()
->getStorage('node')
->getQuery()
->accessCheck(TRUE)
->condition('type', 'product')
->condition('status', 1);
// Ajouter une condition pour chaque taille (AND)
foreach ($sizes as $size_tid) {
$query->condition('field_sizes', $size_tid);
}
$nids = $query->execute();

Afficher les informations de taxonomie dans un template Twig personnalisé.

Créez un template qui affiche :

  • Le nom de la marque avec son logo (si disponible)
  • Les tailles sous forme de badges
  • Les couleurs sous forme de pastilles colorées

Fichier à créer : node--product--teaser.html.twig

Section intitulée « Fichier à créer : node--product--teaser.html.twig »
💡 Solution
{#
/**
* @file
* Theme override for product teaser.
*/
#}
<article{{ attributes.addClass('product-teaser') }}>
{# Image produit #}
{% if content.field_images|render %}
<div class="product-image">
{{ content.field_images.0 }}
</div>
{% endif %}
<div class="product-info">
{# Marque avec logo #}
{% if node.field_brand.entity %}
<div class="product-brand">
{% if node.field_brand.entity.field_brand_logo.entity %}
<img src="{{ file_url(node.field_brand.entity.field_brand_logo.entity.fileuri) }}"
alt="{{ node.field_brand.entity.label }}"
class="brand-logo">
{% else %}
<span class="brand-name">{{ node.field_brand.entity.label }}</span>
{% endif %}
</div>
{% endif %}
{# Titre #}
<h3 class="product-title">
<a href="{{ url }}">{{ label }}</a>
</h3>
{# Catégorie #}
{% if node.field_category.entity %}
<span class="product-category">
{{ node.field_category.entity.label }}
</span>
{% endif %}
{# Prix #}
<div class="product-price">
{{ content.field_price }}
</div>
{# Tailles disponibles #}
{% if node.field_sizes|length > 0 %}
<div class="product-sizes">
<span class="label">Tailles :</span>
{% for size in node.field_sizes %}
<span class="size-badge">{{ size.entity.label }}</span>
{% endfor %}
</div>
{% endif %}
{# Couleurs avec pastilles #}
{% if node.field_colors|length > 0 %}
<div class="product-colors">
<span class="label">Couleurs :</span>
{% for color in node.field_colors %}
<span class="color-swatch"
style="background-color: {{ color.entity.field_color_code.value }}"
title="{{ color.entity.label }}">
</span>
{% endfor %}
</div>
{% endif %}
</div>
</article>

CSS associé :

.product-teaser {
display: flex;
gap: 1rem;
padding: 1rem;
border: 1px solid #eee;
border-radius: 8px;
}
.brand-logo {
max-height: 30px;
width: auto;
}
.size-badge {
display: inline-block;
padding: 2px 8px;
background: #f0f0f0;
border-radius: 4px;
font-size: 0.875rem;
margin-right: 4px;
}
.color-swatch {
display: inline-block;
width: 20px;
height: 20px;
border-radius: 50%;
border: 2px solid #ccc;
margin-right: 4px;
cursor: help;
}

🎯 Exercice 5 : Créer le contenu de démonstration

Section intitulée « 🎯 Exercice 5 : Créer le contenu de démonstration »

Créer le contenu de la boutique TailStore avec les taxonomies.

Créez les contenus suivants :

TitreCatégorieMarqueTaillesCouleursPrix
Nike Air Force 1ChaussuresNike40, 41, 42, 43, 44Blanc, Noir119.99
T-shirt Adidas SportT-shirtsAdidasS, M, L, XLNoir, Bleu35.99
Hoodie Puma EssentialSweatsPumaM, L, XLGris, Noir69.99
Jean Levi’s 501PantalonsLevi’sS, M, LBleu89.99
Sac à main ZaraAccessoiresZara-Beige, Noir49.99
TitreCatégorieExtrait
Les tendances mode été 2025Tendances ModeDécouvrez les couleurs…
Comment choisir ses sneakersConseils StyleGuide complet pour…
Notre client parle de nousTémoignagesInterview de Jean…
💡 Script de création
<?php
/**
* Script pour créer le contenu de démonstration.
* Usage: drush php:script create-demo-content.php
*/
use Drupal\node\Entity\Node;
// Fonction helper pour récupérer un TID par nom
function get_term_id($vid, $name) {
$terms = \Drupal::entityTypeManager()
->getStorage('taxonomy_term')
->getQuery()
->accessCheck(FALSE)
->condition('vid', $vid)
->condition('name', $name)
->execute();
return reset($terms);
}
// Fonction helper pour récupérer plusieurs TIDs
function get_term_ids($vid, $names) {
$terms = \Drupal::entityTypeManager()
->getStorage('taxonomy_term')
->getQuery()
->accessCheck(FALSE)
->condition('vid', $vid)
->condition('name', $names, 'IN')
->execute();
return array_values($terms);
}
// Créer les produits
$products = [
[
'title' => 'Nike Air Force 1',
'category' => 'Chaussures',
'brand' => 'Nike',
'sizes' => ['M', 'L', 'XL'],
'colors' => ['Blanc', 'Noir'],
'price' => 119.99,
'sku' => 'NIKE-AF1-001',
'description' => 'Les légendaires Air Force 1 de Nike. Confort et style intemporel.',
],
[
'title' => 'T-shirt Adidas Sport',
'category' => 'T-shirts',
'brand' => 'Adidas',
'sizes' => ['S', 'M', 'L', 'XL'],
'colors' => ['Noir', 'Bleu'],
'price' => 35.99,
'sku' => 'ADIDAS-TS-001',
'description' => 'T-shirt de sport respirant, idéal pour l\'entraînement.',
],
[
'title' => 'Hoodie Puma Essential',
'category' => 'Sweats',
'brand' => 'Puma',
'sizes' => ['M', 'L', 'XL'],
'colors' => ['Gris', 'Noir'],
'price' => 69.99,
'sku' => 'PUMA-HD-001',
'description' => 'Hoodie confortable avec capuche et poche kangourou.',
],
[
'title' => 'Jean Levi\'s 501',
'category' => 'Pantalons',
'brand' => "Levi's",
'sizes' => ['S', 'M', 'L'],
'colors' => ['Bleu'],
'price' => 89.99,
'sku' => 'LEVIS-501-001',
'description' => 'Le jean iconique 501, coupe droite classique.',
],
[
'title' => 'Sac à main Zara',
'category' => 'Accessoires',
'brand' => 'Zara',
'sizes' => [],
'colors' => ['Beige', 'Noir'],
'price' => 49.99,
'sku' => 'ZARA-SAC-001',
'description' => 'Sac à main élégant en similicuir, parfait pour toutes les occasions.',
],
];
foreach ($products as $data) {
$node = Node::create([
'type' => 'product',
'title' => $data['title'],
'status' => 1,
'field_category' => get_term_id('product_category', $data['category']),
'field_brand' => get_term_id('brand', $data['brand']),
'field_sizes' => $data['sizes'] ? get_term_ids('size', $data['sizes']) : [],
'field_colors' => get_term_ids('color', $data['colors']),
'field_price' => $data['price'],
'field_sku' => $data['sku'],
'field_description' => [
'value' => '<p>' . $data['description'] . '</p>',
'format' => 'basic_html',
],
]);
$node->save();
echo "Produit créé: " . $data['title'] . "\n";
}
// Créer les articles de blog
$articles = [
[
'title' => 'Les tendances mode été 2025',
'category' => 'Tendances Mode',
'body' => 'Découvrez les couleurs et les styles qui vont marquer cet été...',
],
[
'title' => 'Comment choisir ses sneakers',
'category' => 'Conseils Style',
'body' => 'Guide complet pour trouver la paire parfaite selon votre style...',
],
[
'title' => 'Notre client parle de nous',
'category' => 'Témoignages',
'body' => 'Interview de Jean, client fidèle depuis 3 ans...',
],
];
foreach ($articles as $data) {
$node = Node::create([
'type' => 'blog_article',
'title' => $data['title'],
'status' => 1,
'field_blog_category' => get_term_id('blog_category', $data['category']),
'body' => [
'value' => '<p>' . $data['body'] . '</p>',
'format' => 'basic_html',
],
]);
$node->save();
echo "Article créé: " . $data['title'] . "\n";
}
echo "\nContenu de démonstration créé avec succès!\n";

Avant de passer à l’étape suivante, vérifiez :

Vocabulaires

  • 5 vocabulaires créés + Collection
  • Champ code couleur sur Couleur
  • Hiérarchie dans Catégorie Produit

Termes

  • Tous les termes créés
  • Termes ordonnés (Tailles)
  • Codes couleur renseignés

Relations

  • Champs de référence créés
  • Widgets configurés
  • Formatters configurés

Contenu

  • 5 produits de démonstration
  • 3 articles de blog
  • Configuration exportée
Fenêtre de terminal
# Exporter toute la configuration
drush cex -y
# Commiter les changements
cd /path/to/your/drupal
git add config/sync/
git commit -m "feat: add taxonomies and entity references"

Félicitations ! 🎉 Les taxonomies sont en place. Dans l’Étape 4 - Vues, nous allons créer les listes de produits, le catalogue avec filtres, et les blocs dynamiques.