Imaginez que vous utilisez le thème Wordpress Divi, vous avez ajouté un portfolio filtrable pour afficher vos réalisations : sites vitrines, shops en lignes et logos. Le top. Sur l’une de vos pages, vous aimeriez ajouter un lien vers vos réalisations de logos. Comment faire pour passer un paramètre filtrant le portfolio Divi au chargement d’une page ?
Il n’y a malheureusement pas de solution toute faite pour ce problème somme toute assez banal. Par défaut le portfolio de Divi ne dispose pas de cette fonctionnalité.
Comment faire alors ? Il faudra taper dans le code. Mais ne vous inquiétez pas, même si vous êtes un néophyte, vous devriez pouvoir vous débrouiller avec cet article. Le principe est le suivant :
- Copier le code du module de portfolio filtrable directement dans votre thème enfant
- Modifier le code du module de portfolio en tenant compte d’un paramètre passé dans l’URL pour le filtrer au chargement de la page
- Le référencer dans le fichier functions.php de votre thème enfant, afin de l’utiliser à la place du module par défaut
Avant d’entrer dans le vif du sujet, un peu de contexte.
C’est quoi le thème Divi ?
Le thème Divi est un des plus célèbre thème Wordpress payant sur la planète. Proposé avec certains hébergeurs, il s’est assez vite imposé comme une référence.
Bien plus qu’un simple style visuel, Divi offre une quantité d’outils de création. Fourni par défaut avec certains hébergements, notamment Infomaniak, c’est au départ un thème payant développé par la société Elegant Themes.
Elegant Themes est un des mastodontes de la création de thèmes Wordpress. Je travaillais déjà avec certains de leurs thèmes en 2010. Cependant, tous leurs thèmes sont payants et nécessitent un abonnement à leur plate-forme pour pouvoir être utilisés.
Pour travailler avec Divi on utilise le Visual Builder, le “constructeur visuel”, qui permet de modifier le contenu de son site directement en WISIWYG : What You See Is What You Get : ce que vous voyez est ce que vous obtenez.
Divi fonctionne à l’aide de sections, contenant des lignes pouvant se séparer en plusieurs colonnes. Chaque colonne peut contenir un module. Dans Divi, tout contenu passe par un module : texte, titre d’un article, image, galerie de photos, etc.
En plus des nombreux modules de bases, il en existe également une quantité téléchargeable pour étendre encore les capacités de Divi. Et le blog d’Elegant Themes vous proposera également pas mal de solutions pour ajouter ou modifier des fonctionnalités à certains modules par le code. Mais pas celle que je vais vous présenter !
Le module de portfolio filtrable
Divi propose un module appelé Portefeuille filtrable. Il s’agit en fait d’un module de portfolio où vous pourrez filtrer l’affichage de vos travaux par catégorie. Cela permet par exemple d’afficher et filtrer vos réalisations, références ou autre. En pratique, le module de portfolio vous propose d’afficher tous les projets de votre site Wordpress.
Les pré-requis
Pour pouvoir utiliser le portfolio filtrable et le code que je vais vous proposer par la suite, il faut vous assurer d’avoir :
Créé des catégories pour vos projets
Première chose à faire définir des catégories pour vos projets et les ajouter dans la vue catégorie sous le menu Projet.
Une fois dans cette vue, ajoutez simplement les catégories qui vous intéressent. À la création, prenez bien garde à définir vous même le nom du slug
de votre catégorie. Ce nom sera utilisé en paramètre de l’URL lorsque vous souhaiterez créé un lien vers un filtre spécifique de votre portfolio.
Par exemple la catégorie Sites web aura le slug
sites-web. Qui se traduira par une requête de ce type :
/projets/?slug=sites-web
Lorsque vous souhaiterez créer un lien filtrant par défaut votre portfolio sur les projets de type Sites web.
Appliquer ces catégories sur vos projets
Logique mais impératif. Si vous avez déjà créé vos projets mais que ceux-ci n’ont aucune catégorie définie, difficile de créer un filtre fonctionnel.
Pour chaque projet allez donc définir la ou les catégories auxquelles il appartient.
Crée un thème enfant
C’est la bonne pratique par excellence dans Wordpress, ne jamais modifier le thème original, toujours passer par un thème enfant héritant du code du thème de parent.
Vous ne savez pas comment créer un thème enfant ? Vous désirez plus de détails à ce sujet ? Découvrez mon générateur de thème enfant WordPress !
Vous-y trouverez toutes les explications indispensables à ce sujet et vous aurez la possibilité de créer votre thème en un clic !
Le problème
Lorsqu’on veut afficher toutes ces réalisations, aucun soucis, le portfolio de Divi est idéal. Mais si on désire proposer un lien au visiteur pour afficher une catégorie de projet spécifique, ce n’est pas possible nativement.
L’idée est qu’en passant une information en argument dans le lien vers la page de vos projets, on puisse activer un filtre spécifique directement sur la catégorie concernée. Par exemple :
/projets/?slug=sites-web
Ouvrirait notre page de références en filtrant initialement le portfolio sur la catégorie Sites web.
La solution
Le principe
Comme expliqué en préambule, il sera nécessaire d’écrire du code pour régler ce problème. L’idée sera de créer un nouveau module personnalisé à partir du code du portfolio Divi en lui ajoutant ces fonctionnalités.
1. Copier la classe du portfolio filtrable Divi dans votre thème enfant
Pour se faire, rendez-vous dans le dossier du thème Divi présent sous :
/wp-content/themes/Divi
Là vous trouverez toute la structure et le code du thème Divi. Pour trouver cette classe, naviguez dans :
/includes/builder/module/FilterablePortfolio.php
Copiez ce fichier et aller à la racine de votre thème enfant dans /wp-content/themes/[nom de votre thème enfant]
. Là je vous conseil de créer un dossier pour plus de clarté, par exemple custom-modules
. Collez-y votre fichier FilterablePortfolio.php
.
Par convention, je vous conseil de le renommer également, par exemple CustomFilterablePortfolio
. Donc voici le chemin de votre fichier copié :
[nom de votre thème enfant]/custom-modules/CustomFilterablePortfolio.php
2. Modifier la classe portfolio
Ouvrez le fichier CustomFilterablePortfolio.php
pour commencer la modification. Première étape, changer le nom de la classe pour éviter les conflits. Remplacez donc le nom de la classe en tout début de code en la passant de :
<?php
class ET_Builder_Module_Filterable_Portfolio extends ET_Builder_Module_Type_PostBased {
À :
<?php
class Custom_ET_Builder_Module_Filterable_Portfolio extends ET_Builder_Module_Type_PostBased {
Une fois cette opération faite, rendez-vous en bas du document, dans la méthode render
. C’est cette méthode qui s’occupera de générer le portfolio sur votre page web. Rendez-vous aux alentours de la ligne 574 sur la ligne de code :
wp_reset_postdata();
Notez que ce numéro de ligne est susceptible d’être modifié avec les futurs mises à jour du thème Divi. Sous cette ligne se trouve le code suivant :
if ( ! $posts = ob_get_clean() ) {
$posts = self::get_no_results_template();
$category_filters = '';
} else {
$categories_included = explode ( ',', $include_categories );
$terms_args = array(
'include' => $categories_included,
'orderby' => 'name',
'order' => 'ASC',
);
$terms = get_terms( 'project_category', $terms_args );
$category_filters = '<ul class="clearfix">';
$category_filters .= sprintf( '<li class="et_pb_portfolio_filter et_pb_portfolio_filter_all"><a href="#" class="active" data-category-slug="all">%1$s</a></li>',
esc_html__( 'All', 'et_builder' )
);
foreach ( $terms as $term ) {
$category_filters .= sprintf( '<li class="et_pb_portfolio_filter"><a href="#" data-category-slug="%1$s">%2$s</a></li>',
esc_attr( urldecode( $term->slug ) ),
esc_html( $term->name )
);
}
$category_filters .= '</ul>';
}
C’est au sein de ce code que nous allons appliquer nos modifications. Ne tenez pas compte de la première expression conditionnelle :
if ( ! $posts = ob_get_clean() ) {
Cette méthode générera simplement une vue Aucun résultat si elle est vrai. En gros si aucun projet à afficher n’existe.
À partir du else
, ça devient intéressant :
} else {
$categories_included = explode ( ',', $include_categories );
$terms_args = array(
'include' => $categories_included,
'orderby' => 'name',
'order' => 'ASC',
);
$terms = get_terms( 'project_category', $terms_args );
$category_filters = '<ul class="clearfix">';
$category_filters .= sprintf( '<li class="et_pb_portfolio_filter et_pb_portfolio_filter_all"><a href="#" class="active" data-category-slug="all">%1$s</a></li>',
esc_html__( 'All', 'et_builder' )
);
foreach ( $terms as $term ) {
$category_filters .= sprintf( '<li class="et_pb_portfolio_filter"><a href="#" data-category-slug="%1$s">%2$s</a></li>',
esc_attr( urldecode( $term->slug ) ),
esc_html( $term->name )
);
}
$category_filters .= '</ul>';
}
C’est cette partie que nous allons modifier. Ce code fait 4 choses :
- Il commence par récupérer les catégories inclues dans le portfolio filtrable (car il est possible de ne pas toutes les afficher) à partir de la liste de catégories existantes.
- Il crée ensuite un
<ul>
dans lequel il ajoutera un premier élément appelé All donc Tout. Ce premier élément est le premier filtre, il permettra d’afficher tous les projets. Vous pourrez constater que cet élément dispose du codeclass=”active”
. Ce code est très important et permet d’indiquer quel est le filtre actif. Il s’agit donc du filtre par défaut. - Ensuite une boucle passe par toutes les catégories à afficher et créé un élément
<li>
pour chacune d’entre elle - Il ferme le
<ul>
Ce code est ajouté à la variable $category_filters
qui sera affichée par la suite lors du rendu final.
Que cherchons nous à faire avec ça ? Et bien Divi va observer, au chargement de la page, quelle catégorie possède la classe active
afin de filtrer le portfolio en fonction.
Donc nous allons faire la chose suivante :
- Regarder si une valeur pour le paramètre
slug
a été passé à l’URL de la page actuelle - Si c’est le cas nous allons regarder si cet attribut
slug
correspond auslug
d’une des catégories - Si c’est le cas cette catégorie disposera de la classe
active
, en lieu et place de la catégorie par défaut Tout
Voici le code commenté que vous utiliserez pour remplacer le code mentionné ci-dessus :
} else {
$categories_included = explode ( ',', $include_categories );
$terms_args = array(
'include' => $categories_included,
'orderby' => 'name',
'order' => 'ASC',
);
$terms = get_terms( 'project_category', $terms_args );
// Initialise une variable $selected_slug
$selected_slug = "";
// Si un paramètre slug a été passé en paramètre, on l'enregistre dans cette variable
if (isset($_GET["slug"])) {
$selected_slug = $_GET["slug"];
}
// Comme on ne sait pas encore si la catégorie passée en paramètre est valide, on
// enregistre une variable permettant d'enregistrer cette information
$has_selected_slug = false;
// On initialise la variable $category_filters vide plutôt que de lui donner immédiatement
// le <ul> ainsi que le premier filtre "Tout". Nous ne savons pas si "Tout" sera le filtre actif
// donc ce code sera ajouté à la fin
$category_filters = '';
// Cette variable évite d'avoir à copier / coller du code dans les expressions conditionnelles
// elle contiendra la valeur 'class="active"' s'il s'agit de la catégorie active
$active_class = '';
foreach ( $terms as $term ) {
// Pour chaque catégorie, on regarde si la valeur du slug correspond au slug passé en paramètre
// On regarde également si un filtre a déjà été appliqué ou non pour éviter d'appliquer class="active"
// sur plusieurs catégories. Même si ça ne devrait pas arriver car un slug est unique.
if ($term->slug == $selected_slug && !$has_selected_slug) {
// Si c'est le cas, on enregistre la valuer dans $active_class pour l'ajouter plus bas
// Et on indique qu'une catégorie a été trouvée, donc plus besoin de chercher
$active_class = 'class="active"';
$has_selected_slug = true;
} else {
// On ajoute la variable $active_class dans la balise <li>. Rappelez-vous, cette variable peut soit
// contenir l'indication 'class="active"' soit être vide
$category_filters .= sprintf( '<li class="et_pb_portfolio_filter"><a href="#" %1$s data-category-slug="%2$s">%3$s</a></li>',
$active_class,
esc_attr( urldecode( $term->slug ) ),
esc_html( $term->name )
);
// On s'assure de bien vider la variable $active_class pour éviter que la valeur
// persiste à l'itération suivante
$active_class = '';
}
// Si aucun slug n'a été passé en paramètre ou si celui-ci ne correspond à aucune catégorie
// de la liste, on passe $active_class à sa valeur active, afin de bien l'ajouter sur le filtre "Tout"
if (!$has_selected_slug) {
$active_class = 'class="active"';
}
// Et on ajoute le filtre "Tout" au début avec l'ouverture de la balise <ul>
// en ajoutant $active_class, qu'il soit vide ou non
$category_filters = sprintf( '<ul class="clearfix"><li class="et_pb_portfolio_filter et_pb_portfolio_filter_all"><a href="#" %1$s data-category-slug="all">%2$s</a></li>',
$active_class,
esc_html__( 'All', 'et_builder' )
) . $category_filters;
// Puis on ferme le <ul>
$category_filters .= '</ul>';
}
3. Remplacer le module de portfolio Divi avec votre module modifié
Dernière étape, actuellement votre thème enfant ne tient pas compte de votre nouveau module. Vous devez lui indiquer qu’il doit utiliser ce module modifié plutôt que celui par défaut de Divi.
Ouvrez votre fichier functions.php
à la racine de votre thème enfant et ajoutez-y le code suivant. Le code est commenté est devrait se suffir à lui-même :
function divi_child_theme_setup() {
// Commence par vérifier que la class "ET_Builder_Module" existe
// Permet de s'assurer que les classes Divi ont bien été chargées
if ( ! class_exists('ET_Builder_Module') ) {
return;
}
// Récupère la class que vous avez créé dans le sous-dossier custom-modules
get_template_part( 'custom-modules/CustomFilterablePortfolio' );
// Instancie un nouvel objet de type Custom_ET_Builder_Module_Filterable_Portfolio
$cfwpm = new Custom_ET_Builder_Module_Filterable_Portfolio();
// Supprime le shortcode défini par Divi pour le portfolio
remove_shortcode( 'et_pb_filterable_portfolio' );
// Et le recréé en lui appliquant 2 paramètres :
// - L'instance de votre nouvelle classe créée au dessus
// - La méthode à appeler pour le shortcode, avec un "_" devant (convention Wordpress)
add_shortcode( 'et_pb_filterable_portfolio', array($cfwpm, '_render') );
}
add_action( 'wp', 'divi_child_theme_setup', 9999 );
Votre nouveau module est prêt ! 🙂
EDIT : Merci à Fabien en commentaire pour avoir pointé que j’avais oublié la ligne add_action
pour appliquer la modification, sans quoi rien ne se passait !
Conclusion
En fouillant un peu, on arrive toujours à faire ce qu’on veut avec Wordpress et plus spécifiquement Divi.
Le seul problème existant avec cette solution, c’est qu’en cas de mise à jour, le module de portfolio ne profitera pas des nouvelles fonctionnalités implémentés. Celui de votre thème enfant sera toujours utilisé au lieu du module de base de Divi.
Autre soucis potentiel : un changement de fond dans le code du portfolio, de Divi ou de Wordpress pourrait empêcher votre nouveau module de fonctionner en cas d’update. Donc bien garder en tête qu’il s’agit d’éléments à tester en cas de mise à jour, pour éviter les mauvaises surprises.
L’avantages, c’est que cette technique peut-être reproduite. Si votre module ne fonctionne plus comme il devrait, avec la documentation donnée, vous devriez pouvoir le recréer sur la base du code du module mis à jour.
Bonjour,
J’ai mis en place votre méthode pour modifier le FilterablePortfolio.php. En fait tout ce dont j’ai comme besoin est que le filtre du portfolio « All » soit modifié pour qu’il affiche « Tout » comme texte, mon site étant en français.
Je veux donc éviter d’utiliser WPML pour ne traduire que ce module portfolio. J’y suis presque mais le « Tout » ne s’affiche uniquement que lorsque je suis en mode « visual builder » mais en mode normal c’est le All qui s’affiche.
Avez-vous une idée pour résoudre ce qui ne fonctionne pas.
Merci à l’avance.
Denis
Bonjour Denis,
J’ai jeté un oeil à votre site, il semblerait que le problème soit corrigé ? J’ai bien le texte « Tout » en haut. Si vous avez toujours « All » il s’agit probablement du cache du navigateur, videz le cache ou passez par un autre navigateur pour voir le résultat.
J’espère que c’est OK pour vous, bonne suite pour votre projet !
Hello, il vous manque l’action qui va bien pour initialiser la function 🙂
add_action( ‘wp’, ‘divi_child_theme_setup’, 9999 );
Bonjour Fabien,
Merci beaucoup pour le commentaire ! Grosse erreur de ma part effectivement si on n’ajoute pas l’action, il ne se passera pas grand-chose.
C’est corrigé grâce à vous 😉
Hello Thierry,
Je viens de tenter l’action mais de mon côté, j’ai un erreur à la ligne 677, le point d’exclamation n’est pas toléré… y a t il une autre syntaxe ?
Merci pour cet article très instructif !
Bonjour Marion,
En reprenant mon article, je remarque qu’une ligne peut être problématique, car incorrecte :
if ($term->slug == $selected_slug !$has_selected_slug) {
Si l’erreur survient bien sur cette ligne, c’est parce qu’il manque la contrainte && entre les deux termes. Il faut vérifier que les 2 conditions soient correctes. Ce code devient donc :
if ($term->slug == $selected_slug && !$has_selected_slug) {
Vraiment désolé de la coquille ! Et si le problème vient d’ailleurs, n’hésite pas à me copier / coller la partie du code problématique pour que je puisse t’aider.
Bon courage et merci pour le commentaire.
Bonjour,
Merci beaucoup pour votre tutoriel,
Cependant je rencontre une erreur critique à la dernière ligne de mon CustomFilterablePortfolio.php :
Juste ici :
if ( et_builder_should_load_all_module_data() ) {
new ET_Builder_Module_Filterable_Portfolio();
}
Pouvez-vous m’aiguiller ? Ai-je manqué une étape ?
Merci d’avance pour votre aide 🙂
Et voici l’erreur en question :
Parse error: syntax error, unexpected ‘if’ (T_IF), expecting function (T_FUNCTION) or const (T_CONST) in /home/peefczl/www/wp-content/themes/Crimson Factory/custom-modules/CustomFilterablePortfolio.php on line 819
Il y a eu une erreur critique sur ce site.
Bonjour Pierre,
Aïe ! Le problème est que je n’utilise plus Divi sur mes nouveaux projets donc difficile de tester ce problème. Mais il est possible que cette erreur survienne parce que les mises à jour de Divi ont modifié la classe de Portfolio de Divi.
Vous récupérez bien le fichier
/includes/builder/module/FilterablePortfolio.php
comme base ? Il faut vraiment partir de cette version et y apporter les modifications mentionnées dans l’article.Bonjour,
J’ai suivit ce tuto avec beaucoup d’intérêt et de fascination de voir à quel point on peut modifier à notre guise wordpress (à condition de s’y connaitre).
Mais ! Je rencontre actuellement un problème d’erreur critique.
« ( ! ) Fatal error: Uncaught Error: Class ‘Custom_ET_Builder_Module_Filterable_Portfolio’ not found in C:\Users\33695\Local Sites\les-pontonautes\app\public\wp-content\themes\Divi-theme-enfant-creation-new-slang-1642546445\functions.php on line 17
( ! ) Error: Class ‘Custom_ET_Builder_Module_Filterable_Portfolio’ not found in C:\Users\33695\Local Sites\les-pontonautes\app\public\wp-content\themes\Divi-theme-enfant-creation-new-slang-1642546445\functions.php on line 17
Call Stack
# Time Memory Function Location
1 0.0004 365600 {main}( ) …\index.php:0
2 0.0005 366936 require( ‘C:\Users\33695\Local Sites\les-pontonautes\app\public\wp-blog-header.php’ ) …\index.php:17
3 0.3405 14305104 wp( ) …\wp-blog-header.php:16
4 0.3405 14305136 WP->main( ) …\functions.php:1291
5 0.3423 14501344 do_action_ref_array( ) …\class-wp.php:763
6 0.3423 14501344 WP_Hook->do_action( ) …\plugin.php:518
7 0.3423 14501344 WP_Hook->apply_filters( ) …\class-wp-hook.php:327
8 0.6639 31438016 divi_child_theme_setup( ) …\class-wp-hook.php:303 »
Je confirme avoir bien utilisé le fichier source de divi pour mes modifications. J’ai essayé de regeler le problème tout seul mais n’étant clairement pas au niveau en PHP je suis perdu 😀
Bonjour Floran,
Merci de votre commentaire.
Alors le petit problème avec cet article, c’est qu’il date de 2018 et que depuis, Divi a certainement largement évolué. Pas sûr que tout soit encore fonctionnel tel quel. Cependant vu l’erreur on dirait que cela vient de l’instanciation de votre classe Custom_ET_Builder_Module_Filterable_Portfolio, que WordPress ne trouve pas.
Comme vous pouvez le voir, l’erreur est à la ligne 17 de votre fichier functions.php. Je pense qu’elle intervient sur cette ligne :
$cfwpm = new Custom_ET_Builder_Module_Filterable_Portfolio();
Assurez-vous bien que cette ligne :
get_template_part( 'custom-modules/CustomFilterablePortfolio' );
Soit écrite correctement et qu’au sein de votre thème enfant, vous ayez bien un dossier custom-modules avec à l’intérieur un fichier CustomFilterablePortfolio.php. En gros, assurez-vous que le fichier avec votre classe personnalisée soit correctement chargé. Cela ne veut pas dire que vous n’aurez aucune autre erreur plus tard, mais c’est déjà la base de votre problème ici, semble-t-il.
Bon courage !
Bonjour j’ai pas une grosse connaissance dans les modifications profondes de wordpress comme ça, j’ai justement besoin de passer une catégoorie en URL, par défaut on arrive sur tout, donc pas de souci, mais si un lien personnalisé passe en parametre une catégorie, j’ai donc nom de domaine/references/?slug=commerce/, et la modification ne fonctionne pas
C’est un peu pour ça que je ne m’acharne pas sur WP et code from scratch la plupart du temps, ça change très régulièrement et tout est vite obsolete sur wordpress
Divi theme is the most popular theme on WordPress. I see the theme is very flexible. This is from the elegant theme. Thank you for sharing your beautiful information on depth discussion. But i don’t have enough coding idea regarding this.
Bonjour, cela ne fonctionne pas sur mon site, j’ai cette erreur à la place du module dans le visual builder: function(t){return r.default.createElement(M.default,V({rawContentProcesser:C.default.replaceCodeContentEntities},e.props))}
votre tuto fonctionne-t-il toujours? merci!
Bonjour Marti,
Le tuto datant de 2018, je vous avoue que je ne peux plus garantir sa validité aujourd’hui avec les évolutions de Divi. J’avais intégré ça pour un de mes clients qui travaillent encore avec une version plus ancienne de Divi. En cas de mise à jour de la version et si je dois refaire un chantier là-dessus, j’essaierai de vous partager ma solution. Mais dans tous les cas, il est important de bien reprendre le fichier original et d’essayer de garder la même philosophie que ce que je propose ici pour les filtres, si c’est encore possible.
En espérant que vous trouverez la solution à ce problème !
Hi there,
I think you have to update the content. Still Divi is best usable theme for WordPress, please update the content.