Tambahkan Templat Halaman ke WordPress dengan Plugin


Pernahkah Anda ingin membuat templat halaman Anda sendiri, namun tidak memiliki akses ke tema itu sendiri? Saya, sebagai pembuat plugin WordPress, merasa masalah ini sangat mengganggu saat mengembangkan plugin saya. Untungnya solusinya cukup sederhana! Saya akan membawa Anda dengan cepat melalui beberapa baris kode yang Anda perlukan untuk membuat Template Halaman WordPress secara dinamis langsung melalui PHP.

Inspirasi untuk artikel ini dan kejeniusan di balik solusi kode datang dari Tom McFarlin: Saya menggunakan versi kode aslinya yang telah saya edit, yang dapat Anda temukan di GitHub miliknya. Saya terus memasukkan komentarnya (dan juga menambahkan beberapa komentar saya sendiri) karena menurut saya ini sangat membantu dalam menjelaskan apa yang sedang terjadi – saya sendiri tidak bisa mengatakannya dengan lebih baik!

Anda dapat menemukan kode secara keseluruhan dan contoh plugin di bagian paling bawah postingan ini.

Dapatkah kita memulai?

Kode

Kami akan membuat fungsi PHP kami menggunakan Kelas PHP. Bagi Anda yang belum terlalu paham dengan Kelas PHP, Kelas didefinisikan sebagai sebuah objek yang berisi kumpulan fungsi dan variabel yang bekerja sama. Lihat Pendahuluan PHP.net untuk detail lebih lanjut tentang sintaksis dan teori.

Pembungkus kami hanya membutuhkan 3 variabel:

  1. Plugin Slug: Ini hanya digunakan sebagai pengidentifikasi unik untuk plugin.
  2. Instans Kelas: Saat kita menambahkan instance kelas ini ke head WordPress, sebaiknya kita menyimpannya.
  3. Array Template: Seperti yang mungkin bisa Anda tebak, ini adalah array yang menyimpan nama dan judul template.

Ini dia dalam kodenya:

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;

Dapatkan Contoh Kelas

Seperti yang saya katakan sebelumnya, kita akan menambahkan instance kelas kita ke header WordPress menggunakan fungsi add_filter(). Oleh karena itu kita memerlukan metode yang akan mengembalikan (atau membuat) instance ini untuk kita.

Untuk ini, kita memerlukan metode sederhana, yang disebut 'get_instance'. Lihat di bawah;

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

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

	return self::$instance;

}

Ini akan menjadi metode yang dipanggil ketika kelas kita ditambahkan ke head WordPress menggunakan 'add_action()'.

Filter WordPress

Sekarang kita telah memilah metode 'get_instance', kita perlu memilah apa yang terjadi ketika metode tersebut benar-benar dipakai.

Kita akan menggunakan fungsi add_filter() bawaan WordPress untuk menambahkan instance kelas kita ke dalam poin-poin penting di sepanjang garis waktu inisialisasi WordPress. Dengan menggunakan metode ini kita akan memasukkan data templat halaman kita ke dalam slot yang relevan, seperti memberi tahu WordPress file apa yang akan digunakan sebagai templat ketika halaman dipanggil, dan judul yang akan ditampilkan pada menu dropdown di Editor Halaman.

Untuk ini kita perlu menggunakan metode '__construct' (ini akan dijalankan ketika kelas dipakai).

/**
 * 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',
	);

}

Ada 4 hal berbeda yang terjadi di sini (mengabaikan ' $this->templates=array();', yang hanya menyiapkan variabel untuk digunakan);

  1. Baris 9 – 13: Filter ini menambahkan 'register_project_templates' ke hook 'page_attributes_dropdown_pages_args'. Ini adalah mengisi cache WordPress dengan template baru kami, 'menipu' WordPress agar percaya bahwa file template halaman benar-benar ada di direktori template. Ini menambahkan templat halaman ke daftar dropdown pada kotak meta atribut halaman di editor halaman.
  2. Baris 16 – 20: Di sini pada dasarnya kita melakukan hal yang sama seperti blok kode sebelumnya, kecuali kali ini kita juga menambahkan templat halaman (jika dipilih) ke data kiriman yang disimpan.
  3. Baris 23 – 28: Filter ini menambahkan 'template_include' ke hook 'view_project_template'. Ini adalah fungsi yang sangat penting; ini memberi tahu WordPress di mana sebenarnya file templat halaman Anda berada. WordPress akan menggunakan jalur yang disediakan ini untuk merender halaman terakhir.
  4. Baris 31 – 34: Meskipun sederhana, ini sangat penting. Di sinilah Anda menentukan templat halaman yang ingin Anda tambahkan, dan jalur relatif ke file tempat file templat halaman berada (mis. ‘something.php’ ). Saya telah menyertakan satu contoh (yang akan digunakan dalam contoh plugin). Lihat di bawah untuk contoh umum:
$this->templates = array(
	'FILE_PATH_AND_NAME'               => 'TEMPLATE_TITLE',
	'awesome-template.php'             => 'Awesome',
	'templates/organised-template.php' => 'Organised',
);

(Makan, Tidur,) Kode, Ulangi seperlunya.

daftar_proyek_template()

Saya telah menyinggung metode ini sebelumnya; mari kita lihat apa yang sebenarnya dilakukannya.

Pada dasarnya, tujuan metode ini adalah untuk memanipulasi cache WordPress, memasukkan data relevan tentang templat halaman kami di tempat yang tepat. Lihat kodenya terlebih dahulu, dan saya akan menjelaskannya kepada Anda setelahnya.

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;

}

Saat itu juga. Jalur 4 adalah tempat pertama yang harus dilihat. Seperti yang sudah Anda duga, kami membuat 'kunci cache'. Ini akan digunakan sebagai pengidentifikasi unik untuk data templat laman kami. Menggunakan fungsi md5() cukup membuat pengidentifikasi string unik untuk menghindari konflik.

Selanjutnya, pada baris 8, kita mencari dan mengambil cache templat halaman (jika sudah ada): ini akan mengembalikan array jalur dan judul. Pada baris 9-11 kami memeriksa apakah ada keluaran dari kueri cache. Jika ya, bagus. Jika tidak, buat array lokal untuk menampung data yang akan kita gabungkan ke dalam cache.

Langkah selanjutnya sangat penting. Pada baris 14 kami menghapus cache templat halaman yang ada. Jangan khawatir, tidak ada data yang hilang – data disimpan dalam variabel $templates.

Pada baris 18 kami menggabungkan cache templat halaman yang ada dengan entri baru, dan pada baris 22 kami memasukkan kembali seluruh cache templat halaman ke dalam sistem WordPress.

Sederhana!

lihat_proyek_templat()

Kami sekarang menuju metode terakhir kami; di sinilah kami memberi tahu WordPress di mana file templat halaman sebenarnya berada.

/**
 * 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;

}

Baiklah, metode ini akan memeriksa variabel $post global (baris 6). Ia memeriksa apakah templat halaman ( '_wp_page_template' ) telah disetel untuk posting (artinya itu harus berupa halaman). Jika tidak, tidak apa-apa – non-halaman tidak dapat memiliki templat halaman.

Baris 16 menentukan lokasi file templat halaman. Seperti yang telah saya jelaskan di atas, ia memeriksa file templat halaman yang ditentukan di direktori root plugin Anda. (Ini dapat dengan mudah diubah; lihat di bawah.)

// 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 
);

Setelah ini, pada baris 21 – 24, kita hanya memiliki sedikit validasi yang memeriksa apakah file tersebut benar-benar ada. Jika ya, luar biasa! Jika tidak, ya ampun… Kemungkinan besar Anda akan mendapatkan pesan kesalahan PHP jika WordPress tidak dapat menemukan file template, atau bahkan layar kosong. Jika salah satu gejala ini terdengar familier, cukup periksa jalur file template dengan mencetak variabel $file ke layar.

Jika Anda berencana untuk menggunakan kode ini secara komersial (yang bebas Anda lakukan – versi kode saya tidak memiliki lisensi, maka Anda bebas melakukannya sesuka Anda), saya sangat menyarankan Anda meluangkan waktu untuk menangani kesalahan secara maksimal. keandalan.

Itu dia. Setelah kelas kita selesai, hanya ada satu hal yang harus dilakukan – menambahkannya ke head WordPress.

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

Selamat jika Anda berhasil melewatinya! Saya harap apa yang saya sampaikan bermanfaat bagi Anda, dan Anda mendapat manfaat darinya di masa depan!

Seluruh Kode

Di bawah ini adalah seluruh kode untuk plugin agar mudah disalin dan ditempel.

<?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' ) );

Pluginnya

Anda juga dapat mengunduh kode lengkap sebagai plugin di Github.

Tampilan Dekat Editor Pos

Berikut tampilan plugin yang sedang beraksi. Lihat templat halaman yang ditambahkan di bawah Atribut Halaman?