Mettre à jour: Le code a été mis à jour récemment pour fonctionner sur WordPress 4.7+

Avez-vous déjà voulu créer vos propres modèles de page, mais n'avez pas eu accès au thème lui-même ? En tant qu'auteur de plugins WordPress, j'ai trouvé ce problème particulièrement ennuyeux lors du développement de mes plugins. Heureusement, la solution est assez simple ! Je vais vous présenter rapidement les quelques lignes de code dont vous aurez besoin pour créer dynamiquement des modèles de page WordPress directement via PHP.

L'inspiration pour cet article et le génie derrière la solution de code vient de Tom McFarlin: J'utilise ma version modifiée de son code original, que vous pouvez trouver sur son GitHub. J'ai gardé ses commentaires (ainsi que quelques-uns des miens) car je trouve cela très utile pour expliquer ce qui se passe – je n'aurais pas pu mieux le dire moi-même !

Vous pouvez trouver le code dans son intégralité et un exemple de plugin tout en bas de cet article.

Allons-nous commencer?

Le code

Nous allons créer notre fonction PHP en utilisant une classe PHP. Pour ceux d'entre vous qui ne connaissent pas bien les classes PHP, une classe est définie comme un objet qui contient une collection de fonctions et de variables qui fonctionnent ensemble. Vérifiez Présentation de PHP.net pour plus de détails sur la syntaxe et la théorie.

Notre wrapper n'aura besoin que de 3 variables :

  1. Le plug-in Slug : Ceci est simplement utilisé comme identifiant unique pour le plugin.
  2. Instance de classe : Comme nous ajoutons une instance de cette classe à la tête de WordPress, nous ferions mieux de la stocker.
  3. Tableau de modèles : Comme vous pouvez probablement le deviner, il s'agit d'un tableau contenant les noms et les titres des modèles.

Les voici en code :

class PageTemplater {

		/**
         * A Unique Identifier
         */
		 protected $plugin_slug;

        /**
         * A reference to an instance of this class.
         */
        private static $instance;

        /**
         * The array of templates that this plugin tracks.
         */
        protected $templates;

Obtenir une instance de classe

Comme je l'ai dit précédemment, nous allons ajouter une instance de notre classe à l'en-tête WordPress en utilisant le add_filter() une fonction. Nous aurons donc besoin d'une méthode qui retournera (ou créera) cette instance pour nous.

Pour cela, nous aurons besoin d'une méthode simple, qui s'appellera ‘get_instance'. Découvrez-le ci-dessous;

/**
 * Returns an instance of this class. 
 */
public static function get_instance() {

	if( null == self::$instance ) {
		self::$instance = new PageTemplater();
	} 

	return self::$instance;

}

Ce sera la méthode appelée lorsque notre classe sera ajoutée à l'en-tête WordPress en utilisant ‘add_action()'.

Filtres WordPress

Maintenant que nous avons trié la méthode ‘get_instance', nous devons trier ce qui se passe lorsqu'elle est réellement instanciée.

Nous utiliserons la version intégrée de WordPress add_filter() fonction pour ajouter une instance de notre classe dans des points clés le long de la chronologie d'initialisation de WordPress. En utilisant cette méthode, nous insérerons les données de nos modèles de page dans les emplacements pertinents, par exemple en indiquant à WordPress quel fichier utiliser comme modèle lorsque la page est appelée, et le titre à afficher dans le menu déroulant de l'éditeur de page.

Pour cela, nous devons utiliser le ‘__construction' méthode (elle sera exécutée lorsque la classe sera instanciée).

/**
 * Initializes the plugin by setting filters and administration functions.
 */
private function __construct() {

	$this->templates = array();

	// Add a filter to the attributes metabox to inject template into the cache.
	if ( version_compare( floatval( get_bloginfo( 'version' ) ), '4.7', '<' ) ) {

		// 4.6 and older
		add_filter(
			'page_attributes_dropdown_pages_args',
			array( $this, 'register_project_templates' )
		);

	} else {

		// Add a filter to the wp 4.7 version attributes metabox
		add_filter(
			'theme_page_templates', array( $this, 'add_new_template' )
		);

	}

	// Add a filter to the save post to inject out template into the page cache
	add_filter(
		'wp_insert_post_data', 
		array( $this, 'register_project_templates' ) 
	);

	// Add a filter to the template include to determine if the page has our 
	// template assigned and return it's path
	add_filter(
		'template_include', 
		array( $this, 'view_project_template') 
	);

	// Add your templates to this array.
	$this->templates = array(
		'goodtobebad-template.php' => 'It's Good to Be Bad',
	);

}

Il y a 4 choses différentes qui se passent ici (en ignorant ‘ $this->templates = array();', qui ne fait que préparer la variable à utiliser) ;

  1. Lignes 9 à 13: Ce filtre ajoute le ‘register_project_templates' au crochet ‘page_attributes_dropdown_pages_args'. Cela remplit le cache de WordPress avec nos nouveaux modèles, « trompant » WordPress en lui faisant croire que les fichiers de modèle de page existent réellement dans le répertoire de modèles. Cela ajoute les modèles de page à la liste déroulante de la méta-boîte des attributs de page dans l'éditeur de page.
  2. Lignes 16 à 20: Ici, nous faisons essentiellement la même chose que le bloc de code précédent, sauf que cette fois, nous ajoutons également notre modèle de page (s'il est sélectionné) aux données de publication enregistrées.
  3. Lignes 23 à 28: Ce filtre ajoute le ‘template_include' au hook ‘view_project_template'. C'est une fonction très importante; cela indique à WordPress où se trouve réellement votre fichier de modèle de page. WordPress utilisera le chemin fourni par ceci pour rendre la page finale.
  4. Lignes 31 à 34: Bien que ce soit simple, il est très important. C'est ici que vous spécifiez les modèles de page que vous souhaitez ajouter, et le chemin relatif au fichier où se trouve le fichier de modèle de page (par exemple, ‘something.php'). J'ai inclus un exemple (qui sera utilisé dans le plugin d'exemple). Découvrez ci-dessous un exemple général :
$this->templates = array(
	'FILE_PATH_AND_NAME'               => 'TEMPLATE_TITLE',
	'awesome-template.php'             => 'Awesome',
	'templates/organised-template.php' => 'Organised',
);

(Manger, Dormir,) Coder, Répéter si nécessaire.

registre_projet_modèles()

J'ai fait allusion à cette méthode précédemment; voyons ce qu'il fait réellement.

Essentiellement, le but de cette méthode est de manipuler le cache de WordPress, en insérant les données pertinentes sur nos modèles de page aux bons endroits. Jetez d'abord un coup d'œil au code, et je vous en parlerai ensuite.

public function register_project_templates( $atts ) {

	// Create the key used for the themes cache
	$cache_key = 'page_templates-' . md5( get_theme_root() . '/' . get_stylesheet() );

	// Retrieve the cache list. 
	// If it doesn't exist, or it's empty prepare an array
	$templates = wp_get_theme()->get_page_templates();
	if ( empty( $templates ) ) {
		$templates = array();
	} 

	// New cache, therefore remove the old one
	wp_cache_delete( $cache_key , 'themes');

	// Now add our template to the list of templates by merging our templates
	// with the existing templates array from the cache.
	$templates = array_merge( $templates, $this->templates );

	// Add the modified cache to allow WordPress to pick it up for listing
	// available templates
	wp_cache_add( $cache_key, $templates, 'themes', 1800 );

	return $atts;

}

Juste alors. La ligne 4 est le premier endroit à regarder. Comme vous l'avez peut-être deviné, nous générons une “clé de cache”. Il sera utilisé comme identifiant unique pour notre données de modèle de page. L'utilisation de la fonction md5() crée simplement un identifiant de chaîne unique pour éviter tout conflit.

Ensuite, à la ligne 8, nous cherchons et récupérons le cache du modèle de page (s'il existe déjà) : cela renverra un tableau de chemins et de titres. Aux lignes 9 à 11, nous vérifions s'il y a eu une sortie de la requête de cache. Si oui, super. Sinon, créez un tableau local pour contenir les données que nous allons fusionner dans le cache.

La prochaine étape est cruciale. Sur la ligne 14 nous effacer le cache de modèle de page existant. Ne vous inquiétez pas, aucune donnée n'est perdue – elle est stockée dans la variable $templates.

À la ligne 18, nous fusionnons le cache de modèles de page existant avec nos nouvelles entrées, et à la ligne 22, nous réinsérons le cache de modèle de page entier dans le système de WordPress.

Simple!

view_project_template ()

Nous en sommes maintenant à notre méthode finale ; c'est là que nous disons à WordPress où se trouve le vrai fichier de modèle de page.

/**
 * Checks if the template is assigned to the page
 */
public function view_project_template( $template ) {
	
	// Get global post
	global $post;

	// Return template if post is empty
	if ( ! $post ) {
		return $template;
	}

	// Return default template if we don't have a custom one defined
	if ( !isset( $this->templates[get_post_meta( 
		$post->ID, '_wp_page_template', true 
	)] ) ) {
		return $template;
	} 

	$file = plugin_dir_path(__FILE__). get_post_meta( 
		$post->ID, '_wp_page_template', true
	);

	// Just to be safe, we check if the file exist first
	if ( file_exists( $file ) ) {
		return $file;
	} else {
		echo $file;
	}

	// Return template
	return $template;

}

Ok alors, cette méthode vérifiera par rapport à la variable globale $post (ligne 6). Il vérifie si un modèle de page ( ‘_wp_page_template' ) a été défini pour la publication (ce qui signifie qu'il doit s'agir d'une page). Si ce n'est pas le cas, tant pis – les non-pages ne peuvent pas avoir de modèles de page.

La ligne 16 spécifie l'emplacement du fichier de modèle de page. Comme je l'ai indiqué ci-dessus, il recherche le fichier de modèle de page spécifié dans le répertoire racine de votre plugin. (Cela peut cependant être facilement modifié ; voir ci-dessous.)

// Just changing the page template path
// WordPress will now look for page templates in the subfolder 'templates',
// instead of the root
$file = plugin_dir_path(__FILE__). 'templates/' .get_post_meta( 
	$post->ID, '_wp_page_template', true 
);

Après cela, aux lignes 21 à 24, nous avons juste un peu de validation qui vérifie si le fichier existe réellement. Si oui, génial ! Sinon, oh mon Dieu… Vous obtiendrez très probablement un message d'erreur PHP si WordPress ne trouve pas le fichier de modèle, ou même un écran vide. Si l'un de ces symptômes vous semble familier, vérifiez simplement le chemin du fichier de modèle en affichant la variable $file à l'écran.

Si vous envisagez d'utiliser ce code à des fins commerciales (ce que vous êtes libre de faire – ma version du code est fournie sans licence, vous êtes donc libre d'en faire ce que vous voulez), je vous recommande vraiment d'investir du temps dans la gestion des erreurs pour un maximum fiabilité.

C'est ça. Une fois notre classe terminée, il ne reste plus qu'une chose à faire – l'ajouter à l'en-tête WordPress.

add_action( 'plugins_loaded', array( 'PageTemplater', 'get_instance' ) );

Félicitations si vous avez réussi jusqu'au bout ! J'espère que vous avez trouvé ce que j'avais à dire utile et que vous en tirerez profit à l'avenir !

Code entier

Vous trouverez ci-dessous le code complet du plugin pour un copier-coller facile.

<?php
/*
Plugin Name: Page Template Plugin : 'Good To Be Bad'
Plugin URI: http://www.wpexplorer.com/wordpress-page-templates-plugin/
Version: 1.1.0
Author: WPExplorer
Author URI: http://www.wpexplorer.com/
*/

class PageTemplater {

	/**
	 * A reference to an instance of this class.
	 */
	private static $instance;

	/**
	 * The array of templates that this plugin tracks.
	 */
	protected $templates;

	/**
	 * Returns an instance of this class. 
	 */
	public static function get_instance() {

		if ( null == self::$instance ) {
			self::$instance = new PageTemplater();
		} 

		return self::$instance;

	} 

	/**
	 * Initializes the plugin by setting filters and administration functions.
	 */
	private function __construct() {

		$this->templates = array();


		// Add a filter to the attributes metabox to inject template into the cache.
		if ( version_compare( floatval( get_bloginfo( 'version' ) ), '4.7', '<' ) ) {

			// 4.6 and older
			add_filter(
				'page_attributes_dropdown_pages_args',
				array( $this, 'register_project_templates' )
			);

		} else {

			// Add a filter to the wp 4.7 version attributes metabox
			add_filter(
				'theme_page_templates', array( $this, 'add_new_template' )
			);

		}

		// Add a filter to the save post to inject out template into the page cache
		add_filter(
			'wp_insert_post_data', 
			array( $this, 'register_project_templates' ) 
		);


		// Add a filter to the template include to determine if the page has our 
		// template assigned and return it's path
		add_filter(
			'template_include', 
			array( $this, 'view_project_template') 
		);


		// Add your templates to this array.
		$this->templates = array(
			'goodtobebad-template.php' => 'It's Good to Be Bad',
		);
			
	} 

	/**
	 * Adds our template to the page dropdown for v4.7+
	 *
	 */
	public function add_new_template( $posts_templates ) {
		$posts_templates = array_merge( $posts_templates, $this->templates );
		return $posts_templates;
	}

	/**
	 * Adds our template to the pages cache in order to trick WordPress
	 * into thinking the template file exists where it doens't really exist.
	 */
	public function register_project_templates( $atts ) {

		// Create the key used for the themes cache
		$cache_key = 'page_templates-' . md5( get_theme_root() . '/' . get_stylesheet() );

		// Retrieve the cache list. 
		// If it doesn't exist, or it's empty prepare an array
		$templates = wp_get_theme()->get_page_templates();
		if ( empty( $templates ) ) {
			$templates = array();
		} 

		// New cache, therefore remove the old one
		wp_cache_delete( $cache_key , 'themes');

		// Now add our template to the list of templates by merging our templates
		// with the existing templates array from the cache.
		$templates = array_merge( $templates, $this->templates );

		// Add the modified cache to allow WordPress to pick it up for listing
		// available templates
		wp_cache_add( $cache_key, $templates, 'themes', 1800 );

		return $atts;

	} 

	/**
	 * Checks if the template is assigned to the page
	 */
	public function view_project_template( $template ) {
		
		// Get global post
		global $post;

		// Return template if post is empty
		if ( ! $post ) {
			return $template;
		}

		// Return default template if we don't have a custom one defined
		if ( ! isset( $this->templates[get_post_meta( 
			$post->ID, '_wp_page_template', true 
		)] ) ) {
			return $template;
		} 

		$file = plugin_dir_path( __FILE__ ). get_post_meta( 
			$post->ID, '_wp_page_template', true
		);

		// Just to be safe, we check if the file exist first
		if ( file_exists( $file ) ) {
			return $file;
		} else {
			echo $file;
		}

		// Return template
		return $template;

	}

} 
add_action( 'plugins_loaded', array( 'PageTemplater', 'get_instance' ) );

Le plugin

Vous pouvez également télécharger le code complet en tant que plugin sur Github.

Gros plan de l'éditeur de messages

Voici un gros plan du plugin en action. Voir le modèle de page ajouté sous Attributs de page ?

GTBB1

Laisser un commentaire