WordPress thème enfant
Accueil » Conseils & tutoriels sites internet » Tutoriels Wordpress » WordPress : créer un modèle de page sur un thème enfant avec fonction personnalisée

WordPress : créer un modèle de page sur un thème enfant avec fonction personnalisée

Les modèles de page sont une forme de template sous WordPress et permettent d’utiliser une mise en page ou des fonctionnalités précises sur un site internet. Intégrées au thème, elle proposent de manière simple, depuis l’administration du site, d’appliquer un design particulier et d’optimiser à la fois le temps de création mais également de répéter de façon précise un agencement particulier.

Régulièrement, le modèle de page le plus connu est celui de la page de blog sous WordPress, mais pour une raison particulière nous pouvons avoir besoin d’en rajouter, afin de répondre soit à un besoin client, soit pour mettre en place une nouvelle fonctionnalité sur son site WordPress.

Pour créer un modèle de page personnalisé, si l’on a pas développé son propre thème, il est donc plus que nécesssaire de créer un thème enfant (cliquez ici pour voir le tutoriel sur la création d’un thème enfant). En effet, un thème enfant permet non seulement de rajouter des fonctions au thème, mais offre la possibilité de modifier chaque page du site, voire même d’en rajouter. Cette opération est donc absolument à maîtriser.

1/ La demande de création d’un modèle de page

Comme de bien entendu, la cliente n’a pas expressément demandé un modèle de page, mais a exprimé un besoin. Ce besoin est déterminé par l’automatisation de l’affichage sous forme d’images d’une liste de pages verrouillées par code d’accès, mais uniquement si celles-ci ne sont disponibles que depuis six mois maximum.

Il faut donc lister ces pages, en récupérer les images à la une, les liens, et les afficher sans barre latérale (comme elle l’effectuait manuellement) de façon responsive et automatisée. Le besoin exprimait également la nécessité de pouvoir ajouter manuellement du texte sur cette page, au-dessus de la liste des pages privées.

Le thème utilisé est Pinnacle de chez Kadence Themes. Un thème enfant est en place.

La solution à l’expression du besoin se présente donc par la création d’un modèle de page, avec une fonction personnalisée les récupérant selon des critères précis.

2/ Analyse de l’architecture d’un thème : Pinnacle

J’ai choisi ce thème car il correspond dans mon cas à une demande précise sur un site déjà existant. Le thème enfant est en place, uniquement pour ajouter des balises meta dans le header, et pour des favicons personnalisés selon le support du visiteur.

Le thème se décompose en plusieurs parties :
– assets
– languages
– lib
– templates
– themeoptions
– woocommerce

S’ensuit une liste de fichiers php correspondant au thème, à savoir les pages 404, archive, header, footer… Et bien évidemment le functions.php, coeur du thème.

Dans la logique d’un thème enfant, il faut donc bien respecter l’arborescence, pour deux raisons : être bien ordonné et éviter des bugs inattendus.

Le répertoire assets contient les médias du thème, des css, et du js. Tout ceci pourra se révéler fort utile lors de l’ajout de fonctions PHP, afin de se servir directement dans Pinnacle pour récupérer au besoin des éléments, ce qui nous évitera de les recréer.

3/ Création de la fonction PHP

Sur un WordPress de développement, la fonction get_private_pages est ajoutée. Faisons les choses proprement et commentons tout de suite le code :

/**
 * Affichage des pages privées, lien sur l'image à la une
 * @author Cyril CHALAMON pour TEAM EVER 09/01/2016 (Bonne année!)
 * @link https://www.team-ever.com
 * @see Codex https://codex.wordpress.org/Class_Reference/wpdb
 */
function get_private_pages(){

}

Voyez donc que je cite l’auteur, la date, le lien vers le site de l’auteur (utile pour contacter), et un lien vers la documentation de WordPress utilisée dans la fonction.

Première chose à réaliser : sachant que je vais devoir effectuer une requête dans la base de données, j’appelle immédiatement la globale $wpdb, qui va me permettre d’accéder de façon sécurisée aux tables.

/**
 * Affichage des pages privées, lien sur l'image à la une
 * @author Cyril CHALAMON pour TEAM EVER 09/01/2016 (Bonne année!)
 * @link https://www.team-ever.com
 * @see Codex https://codex.wordpress.org/Class_Reference/wpdb
 */
function get_private_pages(){
	//Variable globale base de données WP
	global $wpdb;
}

Je suis à présent prêt à préparer ma requête SQL. Voici ce que cela donne :

/**
 * Affichage des pages privées, lien sur l'image à la une
 * @author Cyril CHALAMON pour TEAM EVER 09/01/2016 (Bonne année!)
 * @link https://www.team-ever.com
 * @see Codex https://codex.wordpress.org/Class_Reference/wpdb
 */
function get_private_pages(){
	//Variable globale base de données WP
	global $wpdb;
	//Requête SQL pour chopper toutes les pages privées
	$queryLink = "SELECT *
					FROM ".$wpdb->prefix."posts
					WHERE post_password != ''
					AND post_status = 'publish'
					AND post_type = 'page'
					AND post_date > NOW() - INTERVAL 180 DAY
					ORDER BY post_date DESC
					";
}

Notez donc que je crée une variable PHP contenant ma requête SQL, mais que cette dernière n’est pas effectuée.
La requête SQL demande donc de tout sélectionner dans la table des articles ($wpdb->prefix. »posts), mais uniquement là où le mot de passe n’est pas vide (la négation s’exprime avec !=), là où les pages sont publiées, où tant qu’on y est il s’agit de pages et non d’articles ou de médias ou autre, et dont la date de publication est inférieure à la date actuelle moins 180 jours (ce qui correspond à minima à six mois, à quelques jours près).

Dans la requête SQL, « NOW() – INTERVAL 180 DAY » utilise à la fois la date native sous MySQL, mais la réduit en utilisant INTERVAL 180 DAY, très utile pour travailler une date précise dans le temps.

La globale $wpdb va justement être utile dans ce cas, je dois en récupérer les résultats. Je réalise donc ceci :

/**
 * Affichage des pages privées, lien sur l'image à la une
 * @author Cyril CHALAMON pour TEAM EVER 09/01/2016 (Bonne année!)
 * @link https://www.team-ever.com
 * @see Codex https://codex.wordpress.org/Class_Reference/wpdb
 */
function get_private_pages(){
	//Variable globale base de données WP
	global $wpdb;
	//Requête SQL pour chopper toutes les pages privées
	$queryLink = "SELECT *
					FROM ".$wpdb->prefix."posts
					WHERE post_password != ''
					AND post_status = 'publish'
					AND post_type = 'page'
					AND post_date > NOW() - INTERVAL 180 DAY
					ORDER BY post_date DESC
					";
	//Envoi de la requête SQL pour récupérer toutes les données dans un tableau
	$private_pages = $wpdb->get_results($queryLink);
}

Je dispose à présent d’une toute nouvelle variable nommée $private_pages, contenant les résultats de ma requête, sous forme de tableau, dont il va falloir traiter les données.

Comme il s’agit d’un tableau, créons une boucle foreach.

/**
 * Affichage des pages privées, lien sur l'image à la une
 * @author Cyril CHALAMON pour TEAM EVER 09/01/2016 (Bonne année!)
 * @link https://www.team-ever.com
 * @see Codex https://codex.wordpress.org/Class_Reference/wpdb
 */
function get_private_pages(){
	//Variable globale base de données WP
	global $wpdb;
	//Requête SQL pour chopper toutes les pages privées
	$queryLink = "SELECT *
					FROM ".$wpdb->prefix."posts
					WHERE post_password != ''
					AND post_status = 'publish'
					AND post_type = 'page'
					AND post_date > NOW() - INTERVAL 180 DAY
					ORDER BY post_date DESC
					";
	//Envoi de la requête SQL pour récupérer toutes les données dans un tableau
	$private_pages = $wpdb->get_results($queryLink);
	//Pour chaque page privée
	foreach ($private_pages as $key => $value) {
	}
}

Donc pour chaque entrée dans $private_pages, à savoir que l’on lit les résultats du tableau ligne par ligne, je dispose donc de toutes les informations de ce que je demande. Donc danss ma liste complète des pages privées, j’ai d’ores et déjà à la fois le lien, mais également le titre, le contenu, etc.
Tout sauf l’image à la une, qui sous WordPress est enregistrée différemment. Il va donc en premier lieu falloir que je la récupère, ce ligne par ligne, car nous en sommes à traiter les données au cas par cas.

WordPress nous aide en la matière avec wp_get_attachment_url(), retournant l’URL de l’image à la une, et demandant en paramètre l’identifiant d’une image à la une, que je n’ai pas. En revanche je peux parallèlement utiliser get_post_thumbnail_id(), qui lui demande en paramètre un identifiant de page ou d’article, et nous retourne un identifiant d’image à la une. Ce qui tombe bien, vu que j’ai accès à toutes les données de chaque page, dont l’ID.

Ma demande va donc s’exprimer de la manière suivante : « donne-moi l’identifiant de l’image à la une, puis de cet identifiant, donne-moi l’URL de l’image à la une ».

Ce qui nous donne donc ceci :

/**
 * Affichage des pages privées, lien sur l'image à la une
 * @author Cyril CHALAMON pour TEAM EVER 09/01/2016 (Bonne année!)
 * @link https://www.team-ever.com
 * @see Codex https://codex.wordpress.org/Class_Reference/wpdb
 */
function get_private_pages(){
	//Variable globale base de données WP
	global $wpdb;
	//Requête SQL pour chopper toutes les pages privées
	$queryLink = "SELECT *
					FROM ".$wpdb->prefix."posts
					WHERE post_password != ''
					AND post_status = 'publish'
					AND post_type = 'page'
					AND post_date > NOW() - INTERVAL 180 DAY
					ORDER BY post_date DESC
					";
	//Envoi de la requête SQL pour récupérer toutes les données dans un tableau
	$private_pages = $wpdb->get_results($queryLink);
	//Pour chaque page privée
	foreach ($private_pages as $key => $value) {
		//$value->ID
		//On choppe l'image à la une
		$imgFull = wp_get_attachment_url( get_post_thumbnail_id($value->ID) );
	}
}

Oui mais… Et si la cliente ne renseigne pas d’image à la une ? Il serait judicieux de prévoir ce cas, qui risque forcément d’arriver.
Testons si l’image à la une existe, et si ce n’est pas le cas, servons-nous directement dans le thème parent pour récupérer une image par défaut :

/**
 * Affichage des pages privées, lien sur l'image à la une
 * @author Cyril CHALAMON pour TEAM EVER 09/01/2016 (Bonne année!)
 * @link https://www.team-ever.com
 * @see Codex https://codex.wordpress.org/Class_Reference/wpdb
 */
function get_private_pages(){
	//Variable globale base de données WP
	global $wpdb;
	//Requête SQL pour chopper toutes les pages privées
	$queryLink = "SELECT *
					FROM ".$wpdb->prefix."posts
					WHERE post_password != ''
					AND post_status = 'publish'
					AND post_type = 'page'
					AND post_date > NOW() - INTERVAL 180 DAY
					ORDER BY post_date DESC
					";
	//Envoi de la requête SQL pour récupérer toutes les données dans un tableau
	$private_pages = $wpdb->get_results($queryLink);
	//Pour chaque page privée
	foreach ($private_pages as $key => $value) {
		//$value->ID
		//On choppe l'image à la une
		$imgFull = wp_get_attachment_url( get_post_thumbnail_id($value->ID) );
		if (empty($imgFull)) {
			$imgFull  = get_template_directory_uri().'/assets/img/post_standard_pgrid.jpg';
		}
	}
}

Bon, si l’image n’existe pas, get_template_directory_uri() (le thème parent) me permet d’aller récupérer celle par défaut. De cette manière la cliente ne sera pas perturbée.

Il ne me reste plus qu’à renvoyer le tout en utilisant Bootstrap (natif sous Pinnacle, merci bien Kadence Theme) :

/**
 * Affichage des pages privées, lien sur l'image à la une
 * @author Cyril CHALAMON pour TEAM EVER 09/01/2016 (Bonne année!)
 * @link https://www.team-ever.com
 * @see Codex https://codex.wordpress.org/Class_Reference/wpdb
 */
function get_private_pages(){
	//Variable globale base de données WP
	global $wpdb;
	//Requête SQL pour chopper toutes les pages privées
	$queryLink = "SELECT *
					FROM ".$wpdb->prefix."posts
					WHERE post_password != ''
					AND post_status = 'publish'
					AND post_type = 'page'
					AND post_date > NOW() - INTERVAL 180 DAY
					ORDER BY post_date DESC
					";
	//Envoi de la requête SQL pour récupérer toutes les données dans un tableau
	$private_pages = $wpdb->get_results($queryLink);
	//Pour chaque page privée
	foreach ($private_pages as $key => $value) {
		//$value->ID
		//On choppe l'image à la une
		$imgFull = wp_get_attachment_url( get_post_thumbnail_id($value->ID) );
		if (empty($imgFull)) {
			$imgFull  = get_template_directory_uri().'/assets/img/post_standard_pgrid.jpg';
		}
		//On affiche le lien avec l'image cliquable dans une div Bootstrap
		echo '<div class="col-md-3 col-xs-12 private-posts" id="post-'.$value->ID.'"><a href="'.$value->guid.'" rel="follow" class="private-links"><img src="'.$imgFull.'" class="private-images hvr-grow" title="'.$value->post_title.'" alt="'.$value->post_title.'"/></a></div>';
	}
}

Ma fonction est enfin prête, elle gère même l’affichage ! Il ne reste plus qu’à mettre en place un modèle de page la récupérant proprement.

4/ Le modèle de page

Nous y voici. Dans mon dossier /templates de mon thème enfant, j’ajoute un fichier php que je nomme « private.php ».

Tout de suite, je le prépare pour le rendre accessible depuis le back-office, dans la partie d’édition de page :

Rien qu’avec ceci, dans le menu déroulant « Modèle » dans l’édition d’une page, j’ai accès à mon modèle. A présent, je dois y rajouter le header, le footer
– le header
– les éléments de page (titre et textes paramétrés dans l’administration)
– la liste de mes pages privées
– le footer

Accéder au header et au footer est d’une aisance redoutable sous WordPress, il me suffit de mettre ceci :

Voici donc, mais il me manque toujours les informations de la page en cours, à savoir le titre et son contenu.

En inspectant le code de Pinnacle, sans m’embêter, je peux donc reproduire la mise en page facilement. Ce qui me donne :

<?php
/*
Template Name: Page Private
*/
?>
<?php get_header(); ?>
<div id="pageheader" class="titleclass">
<div class="header-color-overlay"></div>
    <div class="container">
        <div class="page-header">
            <div class="row">
                <div class="col-md-12">
                    <h1 class="kad-page-title entry-title" itemprop="name headline"><?php the_title(); ?></h1>
                </div>
            </div>
        </div>
    </div><!--container-->
</div>
<div class="container main col-md-12 kt-nosidebar">
    <div class="row">
        <div class="private_header col-md-12">
        	<!-- Contenu de ma page -->
        </div>
    </div>
</div>
<?php get_footer(); ?>

 

D’emblée, je me suis servi de the_title(); qui me retourne systématiquement le titre de la page ou l’article en cours. Bref, tout autant facile que d’aller chercher le header ou le footer.

En ce qui concerne le contenu de la page, tout comme je disposais d’une variable globale $wpdb pour la base de données, j’en ai une autre sous WordPress pour accéder aux pages : la globale $post.

Tout comme $wpdb, je peux donc faire ceci :

        <!--?php global $post; $page = get_post($post->ID);
        ?-->

Et je crée de cette manière une variable $page, contenant toutes les informations de ma page en cours, dont le contenu (ce qui dans mon cas m’intéresse).

Je poursuis donc mon design avec ceci :

<?php
/*
Template Name: Page Private
*/
?>
<?php get_header(); ?>
<div id="pageheader" class="titleclass">
<div class="header-color-overlay"></div>
    <div class="container">
        <div class="page-header">
            <div class="row">
                <div class="col-md-12">
                    <h1 class="kad-page-title entry-title" itemprop="name headline"><?php the_title(); ?></h1>
                </div>
            </div>
        </div>
    </div><!--container-->
</div>
<div class="container main col-md-12 kt-nosidebar">
    <div class="row">
        <div class="private_header col-md-12">
        <?php
        global $post;
        $page = get_post($post->ID);
        ?>

        <?php
            echo $page->post_content;
        ?>
        </div>
    </div>
</div>
<?php get_footer(); ?>

 

C’est bon, j’ai recréé ma page sous Virtue. Il ne me reste plus qu’à afficher la liste de mes pages privées, et justement j’ai déjà ma fonction de prête. Je vais tout de même mettre le tout dans une div bootstrap, pour bien agencer le tout.

Voici donc le résultat final de mon modèle de page avec fonction personnalisée :

<?php
/*
Template Name: Page Private
*/
?>
<?php get_header(); ?>
<div id="pageheader" class="titleclass">
<div class="header-color-overlay"></div>
    <div class="container">
        <div class="page-header">
            <div class="row">
                <div class="col-md-12">
                    <h1 class="kad-page-title entry-title" itemprop="name headline"><?php the_title(); ?></h1>
                </div>
            </div>
        </div>
    </div><!--container-->
</div>
<div class="container main col-md-12 kt-nosidebar">
    <div class="row">
        <div class="private_header col-md-12">
        <?php
        global $post;
        $page = get_post($post->ID);
        ?>

        <?php
            echo $page->post_content;
        ?>
        </div>

        <div class="private_container col-md-12">
        <?php
        echo get_private_pages();
        ?>
        </div>
    </div>
</div>
<?php get_footer(); ?>

 

Ma page s’affiche correctement, et au cas où j’ai même mis en place pour des CSS des ID par image affichée, et une class pour toutes les travailler.

L’ensemble est visible sur le site de L’instant C.

Le tout n’est pas évident de prime abord à mettre en place car cela demande tout de même quelques compétences PHP et MySQL, toutefois la création d’un modèle de page sous WordPress demeure très facile, amusez-vous à en créer !

Imprimer Imprimer
Suivre Cyssoo:

Développeur - formateur

Je cherche à display errors le monde, vous auriez pas la doc' ? Follow me on Twitter !

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.