Cours 6
Thème FSE personnalisé¶

Minimalement, un thème WordPress FSE (Block Based Themes) doit avoir la structure de fichiers suivante :
wp-content/themes/
└── tim_momo/
├── parts/
│ ├── header.html
│ └── footer.html
├── templates/
│ ├── single.html (facultatif)
│ └── index.html
├── theme.json
├── screenshot.png (facultatif)
├── functions.php (facultatif, mais important)
└── style.css
Dossier du thème¶
Dans le dossier wp-content/themes/, créer un dossier pour le nouveau thème, par exemple :
wp-content/themes/tim_momo/
Fichier style.css¶
Un fichier style.css doit être ajouté à la racine du thème.
Même s’il n’est pas utilisé (on verra pourquoi plus tard), ce fichier est requis pour que WordPress reconnaisse le thème.
/*
Theme Name: Tim Montmorency (Momo)
Author: cmontmorency
Description: Un super thème de départ pour WordPress
Requires at least: 6.7
Version: 1.0
*/

On peut ajouter plusieurs autres informations dans le commentaire CSS de ce fichier. Pour voir d'autres possibilités, consultez le fichier style.css d'autres thèmes ou encore mieux, la documentation sur le fichier style.css.
Fichier theme.json¶
Un fichier theme.json doit être ajouté à la racine du thème.
Il permet de contrôler le style global et la configuration des blocs. Beaucoup de configurations peuvent être spécifiées dans ce fichier. Je vous recommande fortement de consulter la documentation sur le fichier theme.json pour en savoir plus.
{
"$schema": "https://schemas.wp.org/wp/6.7/theme.json",
"settings": {
"appearanceTools": true,
"useRootPaddingAwareAlignments": true,
"layout": {
"contentSize": "620px",
"wideSize": "1000px"
},
"spacing": {
"units": ["%", "px", "em", "rem", "vh", "vw"]
},
"typography": {
"fontFamilies": [
{
"fontFamily": "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif",
"name": "System Font",
"slug": "system-font"
}
]
}
},
"templateParts": [
{
"area": "header",
"name": "header"
},
{
"area": "footer",
"name": "footer"
}
],
"version": 3
}
Quelques explications :
"$schema": Ça sert surtout à VS Code pour aider avec l’autocomplétion et la validation du fichier.settings: Cette section contrôle les options disponibles dans l’éditeur et les styles par défaut.templateParts: Définit des régions récurrentes du thème. Par exemple, l'entête, le pied de page, la colonne de gauche, etc. Ce sont les éléments entourés d’un encadré mauve/violet 🟪 dans l'interface d'édition du site !
Système de commentaires HTML¶
Si vous regardez dans les fichiers .html d'un thème, vous verrez que Wordpress utilise des commentaires HTML spéciaux.
Ces commentaires commençant toujours par <!-- wp: et ils ne sont pas de nature explicatives. En vérité, ce sont des instructions pour l’éditeur de blocs Gutemberg !
En gros, les commentaires disent à Gutemberg :
« Voici un bloc que j'aimerais rendre éditable par l'utilisateur dans l'interface d'administration. »
Voici un exemple :
<!-- wp:paragraph {"align":"center"} -->
<p class="has-text-align-center">Proudly Powered by <a href="https://wordpress.org" rel="nofollow">WordPress</a></p>
<!-- /wp:paragraph -->

Pour en apprendre plus sur ce genre de syntaxe, il est souvent plus simple d'étudier ce que les autres thèmes FSE font.
Entête et pied de page¶
Si dans notre modèle, on veut ajouter l'entête du site et le pied de page du site, on ajoute les commentaires suivants :
<!-- wp:template-part {"slug":"header","tagName":"header"} /-->
<!-- wp:template-part {"slug":"footer","tagName":"footer"} /-->
L'option slug est le name du templateParts et doit correspondre au fichier html. Ex: footer.html.
L'option tagName est la balise html utilisée autour du contenu du template part.
Exemple de template header.html¶
<!-- wp:group {"layout":{"inherit":"true"}} -->
<div class="wp-block-group">
<!-- wp:group {"align":"full","layout":{"type":"flex","justifyContent":"space-between"},"style":{"spacing":{"padding":{"bottom":"30px","top":"30px"}}}} -->
<div class="wp-block-group alignfull" style="padding-bottom:30px;padding-top:30px">
<!-- wp:group {"layout":{"type":"flex"}} -->
<div class="wp-block-group">
<!-- wp:site-logo {"width":64} /-->
<!-- wp:group -->
<div class="wp-block-group">
<!-- wp:site-title /-->
<!-- wp:site-tagline /-->
</div>
<!-- /wp:group -->
</div>
<!-- /wp:group -->
<!-- wp:navigation {"layout":{"type":"flex","setCascadingProperties":true,"justifyContent":"right","orientation":"horizontal"},"style":{"spacing":{"margin":{"top":"0"}}}} /-->
</div>
<!-- /wp:group -->
</div>
<!-- /wp:group -->
<!-- wp:spacer {"height":50} -->
<div style="height:50px" aria-hidden="true" class="wp-block-spacer"></div>
<!-- /wp:spacer -->
Modèles¶
Le dossier templates contient les modèles de page.
Il en existe plusieurs. Voici un liste non exhaustive :
| Fichier | Utilisé pour… |
|---|---|
index.html |
Template par défaut (minimum requis) |
single.html |
Un article de blog individuel (post) |
page.html |
Une page WordPress (page) |
archive.html |
Une archive générique (catégorie, étiquette, auteur, etc.) |
404.html |
Page d’erreur 404 |
search.html |
Résultats de recherche |
home.html |
Page des articles du blog (si page d’accueil = statique) |
Diagramme sur la hiérarchie des modèles de page en Wordpress.

Générer un thème¶
Il existe des outils très faciles à utiliser pour générer des thèmes personnalisés :
- https://fullsiteediting.com/block-theme-generator/
- https://wordpress.org/plugins/create-block-theme/
Scripts et CSS¶
Pour charger des scripts JavaScript ou des feuilles de style CSS, on peut le faire dans le fichier functions.php de notre thème.
Par exemple si on veut inclure Bootstrap 5 dans notre projet, voici le bout de code à ajouter.
<?php
// ...
// @todo: Changer tim_momo par le nom de votre thème
function tim_momo_enqueue_bootstrap() {
wp_enqueue_style('bootstrap-css', 'https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css', [], 5.3);
wp_enqueue_script('bootstrap-js', 'https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js', [], 5.3, true);
}
// @todo: Changer tim_momo par le nom de votre thème
add_action('wp_enqueue_scripts', 'tim_momo_enqueue_bootstrap');
Pour tout ce qui est personnalisé, c'est la même méthode.
<?php
// ...
// @todo: Changer tim_momo par le nom de votre thème
function tim_momo_enqueue_assets() {
wp_enqueue_style( 'mon_css_custom', get_template_directory_uri() . '/assets/css/salut.css' );
wp_enqueue_script( 'mon_script_custom', get_template_directory_uri() . '/assets/js/bonjour.js', [], '1.0', true );
}
// @todo: Changer tim_momo par le nom de votre thème
add_action( 'wp_enqueue_scripts', 'tim_momo_enqueue_assets' );
Chargement dans l'administration¶
Si on ajoute pas ceci, les styles ne seront pas visibles lorsqu'on les modifie.
<?php
// ...
function tim_momo_editor_styles() {
add_editor_style( 'https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css' );
add_editor_style( './assets/css/styles.css' );
}
add_action( 'after_setup_theme', 'tim_momo_editor_styles' );
Devoir¶

Devoir - Wordpress
One more time
Sous-thème FSE¶
Lorsqu’on souhaite développer un site à partir d’un thème FSE existant, il n’est pas recommandé de modifier directement le thème original.
À la place, il faut créer un thème enfant (ou sous-thème) basé sur ce thème FSE. Cela permet de préserver vos modifications, même si le thème parent est mis à jour ultérieurement. En effet, une mise à jour écraserait les fichiers du thème parent, mais le thème enfant reste intact.
Rien de plus simple à faire ! Il suffit d'utiliser le bon vieux plugin Create Block Theme.

Tout ce qu'il faut s'avoir c'est que dans le thème enfant, un fichier css a été généré et qu'il contient l'information Template. C'est la valeur de cette information qui lie l'enfant à son parent.
/*
Theme Name: Kid
Requires at least: 6.7
Tested up to: 6.7
Requires PHP: 5.7
Template: twentytwentyfive
Text Domain: kid
*/
Développement¶
Quand on développe un thème FSE, ça peut être frustrant de ne pas pouvoir tester l'enregistrement d'un template.
On peut revenir en arrière en réinitialisant le layout programmé. Pour ce faire, il faut aller dans Apparence > Editor > Templates et cliquer sur les trois points verticaux associés au template en question. Sélectionnez ensuite «Reset».

PHP¶

PHP est un langage interprété côté serveur utilisé principalement pour générer du contenu dynamique sur le web.
WordPress utilise PHP pour générer des contenus et les récupérer dans une base de données.
Exécuter du PHP¶
- Un fichier PHP doit avoir l’extension
.php. - Le fichier principal d’un site est souvent
index.php(comme en html). - Un code PHP est toujours entouré des balises PHP :
<?php
// Code PHP ici
?>
Hello world¶
Pour afficher du texte dans la page HTML, on utilise la fonction echo.
<?php
echo "Salut JS !";
?>
document.write("Bonjour monsieur PHP !");
Go on essaye !
Affichons notre fameux et tout premier "Hello world" en PHP !
Commentaires¶
<?php
// Ceci est un commentaire sur une seule ligne
# Ceci est aussi un commentaire sur une seule ligne
/* Ceci est un commentaire sur
plusieurs lignes. */
?>
// Ceci est un commentaire sur une seule ligne
/* Ceci est un commentaire sur
plusieurs lignes. */
Variables¶

En PHP, les variables commencent par le symbole $.
<?php
$title = "1984"; // Chaîne de caractères
$publication_year = 1949; // Nombre entier
$price = 9.99; // Nombre flottant
$recommended = true; // Booléen
$genres = ["science-fiction", "dystopique"]; // Tableau
?>
let title = "1984"; // Chaîne de caractères
let publication_year = 1949; // Nombre entier
let price = 9.99; // Nombre flottant
let recommended = true; // Booléen
let genres = ["science-fiction", "dystopique"]; // Tableau
Les tableaux associatifs¶
<?php
$livre = [
"titre" => "1984",
"auteur" => "George Orwell",
"annee" => 1949
];
echo $livre["titre"]; // 1984
?>
let livre = {
titre: "1984",
auteur: "George Orwell",
annee: 1949
};
console.log(livre.titre); // 1984
Les constantes¶
<?php
const PI = 3.14159;
echo PI; // 3.14159
?>
const PI = 3.14159;
console.log(PI); // 3.14159
Concaténation¶
La concaténation permet d'assembler plusieurs chaînes de caractères pour former un texte complet.
En PHP, on utilise le point (.) pour concaténer des chaînes :
<?php
$nom = "JF";
$message = "Salut " . $nom . " !";
echo $message; // Affiche : Salut JF !
?>
let nom = "JF";
let message = "Salut " + nom + " !";
console.log(message);
Interpolation de chaîne¶
PHP permet d’insérer une variable directement dans une chaîne avec les guillemets ", mais pas avec l'apostrophe '.
<?php
$nom = "JF";
echo "Salut $nom !"; // Affiche : Salut JF !
echo 'Salut $nom !'; // Affiche : Salut $nom !
?>
let nom = "JF";
console.log(`Salut ${nom} !`); // Affiche : Salut JF !
console.log('Salut ${nom} !'); // Affiche : Salut ${nom} !
console.log("Salut ${nom} !"); // Affiche : Salut ${nom} !
En JavaScript on appelle le concept template literals.
Les opérateurs¶
Opérateurs mathématiques¶
<?php
$a = 10;
$b = 5;
echo $a + $b; // 15
echo $a - $b; // 5
echo $a * $b; // 50
echo $a / $b; // 2
echo $a % $b; // 0 (modulo)
?>
let a = 10;
let b = 5;
console.log(a + b); // 15
console.log(a - b); // 5
console.log(a * b); // 50
console.log(a / b); // 2
console.log(a % b); // 0 (modulo)
Opérateurs de comparaison¶
Les opérateurs de comparaison sont souvent utilisés dans les conditions (if).
<?php
$a = 10;
$b = 5;
$a == $b # Vrai si $a est égal à $b (sans vérifier le type).
$a === $b # Vrai si $a est égal à $b et du même type.
$a != $b # Vrai si $a est différent de $b.
$a !== $b # Vrai si $a est différent de $b ou de type différent.
$a < $b # Vrai si $a est inférieur à $b.
$a > $b # Vrai si $a est supérieur à $b.
?>
let a = 10;
let b = 5;
a == b // Vrai si a est égal à b (sans vérifier le type).
a === b // Vrai si a est égal à b et du même type.
a != b // Vrai si a est différent de b.
a !== b // Vrai si a est différent de b ou de type différent.
a < b // Vrai si a est inférieur à b.
a > b // Vrai si a est supérieur à b.
Structures conditionnelles¶
if¶
<?php
$celcius = 100;
if ($celcius < 116) {
echo "Zut ! Ma meringue italienne ne prend pas";
} elseif ($celcius >= 116 && $celcius <= 118) {
echo "Juste à point";
} else {
echo "Fudge ! La meringue italienne cristallise";
}
?>
let celcius = 100;
if (celcius < 116) {
console.log("Zut ! Ma meringue italienne ne prend pas");
} else if (celcius >= 116 && celcius <= 118) {
console.log("Juste à point");
} else {
console.log("Fudge ! La meringue italienne cristallise");
}
switch¶
<?php
$note = "B";
switch ($note) {
case "A":
echo "Excellente note !!!";
break;
case "B":
echo "Bonne note !";
break;
default:
echo "C'est une note";
}
?>
let note = "B";
switch (note) {
case "A":
console.log("Excellente note !!!");
break;
case "B":
console.log("Bonne note !");
break;
default:
console.log("C'est une note");
}
PHP
HTML¶
PHP s'intègre carrément dans du HTML
<?php $nom = "JF"; ?>
<!DOCTYPE html>
<html>
<head>
<title>PHP ♥ HTML</title>
</head>
<body>
<h1><?php echo $nom . " salut ses <strong>droogies</strong> !"; ?></h1>
</body>
</html>

<!DOCTYPE html>
<html>
<head>
<title>PHP ♥ HTML</title>
</head>
<body>
<h1>JF salut ses <strong>droogies</strong> !</h1>
</body>
</html>
Boucles¶

for()¶
<?php
for ($i = 0; $i < 5; $i++) {
echo "index $i /";
// ou
// echo "index " . $i . "/";
}
// Affiche : index 0 /index 1 /index 2 /index 3 /index 4 /
?>
for (let i = 0; i < 5; i++) {
console.log(`Itération ${i}`);
// ou
console.log("Itération " + i);
}
while()¶
<?php
$i = 0;
while ($i < 5) {
echo "Valeur : $i <br>";
$i++;
}
?>
let i = 0;
while (i < 5) {
console.log("Valeur : " + i);
i++;
}
foreach()¶
<?php
$fruits = ["Tomate", "Concombre", "Aubergine", "Piment", "Olive"];
foreach ($fruits as $fruit) {
echo $fruit . "<br>";
}
// Affiche : Tomate<br>Concombre<br>Aubergine<br>Piment<br>Olive<br>
?>
let fruits = ["Tomate", "Concombre", "Aubergine", "Piment", "Olive"];
fruits.forEach(
fruit => console.log(fruit)
);
Fonctions¶
<?php
function pythagore($a, $b) {
return sqrt($a ** 2 + $b ** 2);
}
echo pythagore(3, 4); // Affiche : 5
?>
function pythagore(a, b) {
return Math.sqrt(a ** 2 + b ** 2);
}
console.log(pythagore(3, 4)); // Affiche : 5
Fonctions PHP courantes¶
Longueur d'une chaîne de caractères
<?php
$texte = "Bonjour";
echo strlen($texte); // 7
?>
let texte = "Bonjour";
console.log(texte.length); // 7
Convertion de chaîne en minuscules ou majuscules
<?php
$texte = "Bonjour";
echo strtolower($texte); // bonjour
echo strtoupper($texte); // BONJOUR
?>
let texte = "Bonjour";
console.log(texte.toLowerCase()); // bonjour
console.log(texte.toUpperCase()); // BONJOUR
Suppression des espaces au début et à la fin d'une chaîne
<?php
$texte = " Bonjour ";
echo trim($texte); // "Bonjour"
?>
let texte = " Bonjour ";
console.log(texte.trim()); // "Bonjour"
Remplacement de caractères
<?php
$texte = "Bonjour";
echo str_replace("o", "a", $texte); // Banjaur
?>
let texte = "Bonjour";
console.log(texte.replace("o", "a")); // Banjaur
Nombre d'éléments dans un tableau
<?php
$array = [1, 2, 3, 4, 5];
echo count($array); // 5
?>
let array = [1, 2, 3, 4, 5];
console.log(array.length); // 5
Vérifier si une valeur est dans un tableau
<?php
$array = ["pomme", "banane", "orange"];
if(in_array("banane", $array)) {
echo "Oui";
} else {
echo "Non";
}
?>
let array = ["pomme", "banane", "orange"];
if(array.includes("banane")) {
console.log("Oui");
} else {
console.log("Non");
}
Arrondir un nombre
<?php
$nombre = 4.6;
echo round($nombre); // 5
?>
let nombre = 4.6;
console.log(Math.round(nombre)); // 5
Générer un nombre aléatoire
<?php
echo rand(1, 10); // Nombre entre 1 et 10
?>
console.log(Math.floor(Math.random() * 10) + 1); // Nombre entre 1 et 10
Validation et sécurité des entrées utilisateur¶
Vérifier si une variable est définie : isset($variable)
Vérifier si une variable est vide : empty($variable)
Convertit les caractères spéciaux (< > & " ') en entités HTML : htmlspecialchars($input)
Formulaire¶

<form method="post" action="traitement.php">
<input type="text" name="nom" placeholder="Votre nom">
<input type="hidden" name="identifiant" value="23487102948">
<button type="submit">Envoyer</button>
</form>
<?php
if (isset($_POST['nom'])) {
echo "Bonjour, " . $_POST['nom'];
}
if (isset($_POST['identifiant'])) {
echo "Votre id unique est " . $_POST['identifiant'];
}
?>
Sécurité¶

Injection XSS, ça vous dit quelque chose ? C'est lorsque l'utilisateur entre du contenu malveillant dans un formulaire et que le contenu est affiché directement sur la page.
Par exemple, dans un formulaire, si l'utilisateur entre comme valeur dans le champ prénom la valeur suivante : <script>alert('Hacked!');</script>, cela pourrait poser problème.
Si en php on prend la valeur $_POST['prenom'] et on l'enregistre sur le site, et que si on fait un affichage de cette valeur, n'importe où sur le site, une alerte s'affichera.
Imaginez ce qui pourrait arriver si le script exécute du code malveillant.
<form method="post">
<!-- L’attaquant entre ceci dans le champ nom :
"><script>alert("Hacked!")</script>
-->
<input type="text" name="nom">
<button type="submit">Envoyer</button>
</form>
<?php
$nom = $_POST['nom'];
if (isset($nom)) {
// ❌ Aucune protection
echo "Bonjour, " . $nom;
// ⚠️ Ok
echo "Bonjour, " . htmlspecialchars($nom);
// ✅ Sécurisé
echo "Bonjour, " . htmlspecialchars($nom, ENT_QUOTES, 'UTF-8');
}
?>
| Avant | Apres |
|---|---|
"><script>alert("XSS")</script> |
"><script>alert("XSS")</script> |
Les caractères spéciaux sont convertis en entités HTML, empêchant leur exécution !
Récapitulatif¶

Regardons ce script et analysons son fonctionnement.
<?php
function obtenirMessage($nb, $msg) {
if ($nb >= 80) {
return $msg["excellent"];
} elseif ($nb >= 50) {
return $msg["moyen"];
} else {
return $msg["faible"];
}
}
$nom_utilisateur = isset($_POST["nom"]) ? htmlspecialchars($_POST["nom"], ENT_QUOTES, 'UTF-8') : "Invité";
$note = rand(0, 100);
$messages = [
"excellent" => "Bravo, $nom_utilisateur ! Tu as un score impressionnant ! 🎉",
"moyen" => "Pas mal, $nom_utilisateur. Tu peux encore progresser ! 💪",
"faible" => "Oups, $nom_utilisateur... Il faut réessayer ! 😅"
];
echo "<h1>Bienvenue, $nom_utilisateur !</h1>";
echo "<p>Ta note est de <strong>$note</strong>%.</p>";
echo "<p>" . obtenirMessage($note, $messages) . "</p>";
$matieres = ["Philosophie", "Mathématiques", "Biologie", "Astronomie"];
echo "<h2>Matières :</h2>";
echo "<ul>";
foreach ($matieres as $matiere) {
echo "<li>$matiere</li>";
}
echo "</ul>";
$choix_matiere = "Philosophie";
echo "<h2>Matière préférée :</h2>";
switch ($choix_matiere) {
case "Philosophie":
echo "<p>Ah, l'art de comprendre le monde.</p>";
break;
case "Mathématiques":
echo "<p>Oh, le langage de la nature !</p>";
break;
default:
echo "<p>Intéressant !</p>";
}
?>
<hr>
<form method="post" action="index.php">
<label for="nom">Entre ton nom :</label>
<input type="text" name="nom" id="nom" placeholder="Ex : Nietzsche" required>
<button type="submit">Envoyer</button>
</form>
Exercices¶

Exercice - PHP
Copenhague