यह @kaiser उत्तर के लिए एक वैकल्पिक तरीका है , कि मुझे बहुत अच्छा लगा (मेरे से +1) लेकिन कोर WP फ़ंक्शन के साथ उपयोग करने के लिए अतिरिक्त काम करने की आवश्यकता है और यह टेम्पलेट पदानुक्रम के साथ कम-से-कम एकीकृत है।
मैं जिस दृष्टिकोण को साझा करना चाहता हूं, वह एकल वर्ग पर आधारित है (यह मेरे द्वारा काम कर रहे कुछ से एक छीन लिया गया संस्करण है) जो टेम्प्लेट के लिए डेटा प्रस्तुत करने का ध्यान रखता है।
इसकी कुछ (IMO) दिलचस्प विशेषताएं हैं:
- टेम्प्लेट मानक वर्डप्रेस टेम्प्लेट फाइलें (सिंगल.फपी, पेज. एफपी) हैं, उन्हें थोड़ी अधिक शक्ति मिलती है
- मौजूदा टेम्पलेट सिर्फ काम करते हैं, इसलिए आप बिना किसी प्रयास के मौजूदा थीम से टेम्पलेट को एकीकृत कर सकते हैं
- @kaiser दृष्टिकोण के विपरीत , टेम्प्लेट में आप
$this
कीवर्ड का उपयोग करके चर का उपयोग करते हैं : यह आपको अपरिभाषित चर के मामले में उत्पादन में नोटिस से बचने की संभावना देता है।
Engine
कक्षा
namespace GM\Template;
class Engine
{
private $data;
private $template;
private $debug = false;
/**
* Bootstrap rendering process. Should be called on 'template_redirect'.
*/
public static function init()
{
add_filter('template_include', new static(), 99, 1);
}
/**
* Constructor. Sets debug properties.
*/
public function __construct()
{
$this->debug =
(! defined('WP_DEBUG') || WP_DEBUG)
&& (! defined('WP_DEBUG_DISPLAY') || WP_DEBUG_DISPLAY);
}
/**
* Render a template.
* Data is set via filters (for main template) or passed to method for partials.
* @param string $template template file path
* @param array $data template data
* @param bool $partial is the template a partial?
* @return mixed|void
*/
public function __invoke($template, array $data = array(), $partial = false)
{
if ($partial || $template) {
$this->data = $partial
? $data
: $this->provide(substr(basename($template), 0, -4));
require $template;
$partial or exit;
}
return $template;
}
/**
* Render a partial.
* Partial-specific data can be passed to method.
* @param string $template template file path
* @param array $data template data
* @param bool $isolated when true partial has no access on parent template context
*/
public function partial($partial, array $data = array(), $isolated = false)
{
do_action("get_template_part_{$partial}", $partial, null);
$file = locate_template("{$partial}.php");
if ($file) {
$class = __CLASS__;
$template = new $class();
$template_data = $isolated ? $data : array_merge($this->data, $data);
$template($file, $template_data, true);
} elseif ($this->debug) {
throw new \RuntimeException("{$partial} is not a valid partial.");
}
}
/**
* Used in templates to access data.
* @param string $name
* @return string
*/
public function __get($name)
{
if (array_key_exists($name, $this->data)) {
return $this->data[$name];
}
if ($this->debug) {
throw new \RuntimeException("{$name} is undefined.");
}
return '';
}
/**
* Provide data to templates using two filters hooks:
* one generic and another query type specific.
* @param string $type Template file name (without extension, e.g. "single")
* @return array
*/
private function provide($type)
{
$generic = apply_filters('gm_template_data', array(), $type);
$specific = apply_filters("gm_template_data_{$type}", array());
return array_merge(
is_array($generic) ? $generic : array(),
is_array($specific) ? $specific : array()
);
}
}
( यहाँ Gist के रूप में उपलब्ध है।)
कैसे इस्तेमाल करे
केवल एक चीज की जरूरत है Engine::init()
विधि को कॉल करने के लिए, शायद 'template_redirect'
हुक पर । जो थीम में functions.php
या प्लगइन से किया जा सकता है ।
require_once '/path/to/the/file/Engine.php';
add_action('template_redirect', array('GM\Template\Engine', 'init'), 99);
बस इतना ही।
आपके मौजूदा टेम्प्लेट एक्सपैक्टेड के रूप में काम करेंगे। लेकिन अब आपके पास कस्टम टेम्प्लेट डेटा तक पहुंचने की संभावना है।
कस्टम टेम्पलेट डेटा
टेम्प्लेट डेटा कस्टम करने के लिए दो फ़िल्टर हैं:
'gm_template_data'
'gm_template_data_{$type}'
पहले एक को सभी टेम्प्लेट के लिए निकाल दिया जाता है, दूसरा टेम्प्लेट विशिष्ट होता है, वास्तव में, डायमिक हिस्सा {$type}
फ़ाइल एक्सटेंशन के बिना टेम्प्लेट फ़ाइल का बेसनेम होता है।
उदाहरण के 'gm_template_data_single'
लिए single.php
टेम्पलेट में डेटा पास करने के लिए फ़िल्टर का उपयोग किया जा सकता है ।
इन हुक से जुड़ी कॉलबैक में एक सरणी वापस करनी होती है , जहां कुंजी चर नाम होते हैं।
उदाहरण के लिए, आप मेटा डेटा को पसंद कर सकते हैं क्योंकि टेम्पलेट डेटा पसंद करता है:
add_filter('gm_template_data', function($data) {
if (is_singular()) {
$id = get_queried_object_id();
$data['extra_title'] = get_post_meta($id, "_theme_extra_title", true);
}
return $data;
};
और फिर, टेम्पलेट के अंदर आप केवल उपयोग कर सकते हैं:
<?= $this->extra_title ?>
डिबग मोड
जब दोनों स्थिरांक WP_DEBUG
और WP_DEBUG_DISPLAY
सत्य होते हैं, तो क्लास वर्किन डिबग मोड। इसका मतलब है कि अगर एक चर को परिभाषित नहीं किया गया है तो एक अपवाद फेंक दिया जाता है।
जब वर्ग डिबग मोड में नहीं होता है (शायद उत्पादन में) एक अपरिभाषित चर तक पहुंच एक खाली स्ट्रिंग का उत्पादन करेगा।
डेटा मॉडल
अपने डेटा को व्यवस्थित करने का एक अच्छा और मुख्य तरीका मॉडल कक्षाओं का उपयोग करना है।
वे बहुत सरल वर्ग हो सकते हैं, जो ऊपर वर्णित समान फिल्टर का उपयोग करके डेटा लौटाते हैं। पालन करने के लिए कोई विशेष इंटरफ़ेस नहीं है, उन्हें आपकी प्राथमिकता के लिए व्यवस्थित किया जा सकता है।
नीचे, बस एक उदाहरण है, लेकिन आप अपने तरीके से करने के लिए स्वतंत्र हैं।
class SeoModel
{
public function __invoke(array $data, $type = '')
{
switch ($type) {
case 'front-page':
case 'home':
$data['seo_title'] = 'Welcome to my site';
break;
default:
$data['seo_title'] = wp_title(' - ', false, 'right');
break;
}
return $data;
}
}
add_filter('gm_template_data', new SeoModel(), 10, 2);
__invoke()
विधि (कि रन जब एक वर्ग के एक कॉलबैक की तरह प्रयोग किया जाता है) की ओर से एक स्ट्रिंग के लिए प्रयोग की जाने वाली <title>
टेम्पलेट के टैग।
इस तथ्य के लिए धन्यवाद कि दूसरा तर्क पास किया 'gm_template_data'
गया टेम्पलेट नाम है, विधि होम पेज के लिए एक कस्टम शीर्षक देता है।
ऊपर कोड होने के बाद, कुछ का उपयोग करना संभव है
<title><?= $this->seo_title ?></title>
<head>
पृष्ठ के अनुभाग में।
partials
वर्डप्रेस में फ़ंक्शंस होते हैं get_header()
या get_template_part()
जिनका उपयोग मुख्य धारा में भाग को लोड करने के लिए किया जा सकता है।
ये फ़ंक्शन, अन्य सभी वर्डप्रेस फ़ंक्शन की तरह, Engine
क्लास का उपयोग करते समय टेम्प्लेट में उपयोग किया जा सकता है ।
एकमात्र समस्या यह है कि कोर वर्डप्रेस फ़ंक्शंस का उपयोग करके लोड किए गए भाग के अंदर कस्टम टेम्पलेट डेटा प्राप्त करने की उन्नत सुविधा का उपयोग करना संभव नहीं है $this
।
इस कारण से, Engine
क्लास में एक विधि है partial()
जो एक आंशिक (पूरी तरह से बच्चे-विषय संगत तरीके से) लोड करने की अनुमति देती है और फिर भी कस्टम टेम्पलेट डेटा को आंशिक रूप से उपयोग करने में सक्षम है।
उपयोग बहुत सरल है।
यह मानते हुए कि partials/content.php
थीम (या चाइल्ड थीम) फ़ोल्डर के अंदर एक फाइल है , इसका उपयोग करके इसे शामिल किया जा सकता है:
<?php $this->partial('partials/content') ?>
अंदर कि सभी मूल विषय डेटा तक पहुंचने के लिए आंशिक रूप से संभव है उसी तरह से है।
वर्डप्रेस फ़ंक्शंस के विपरीत, Engine::partial()
विधि विशिष्ट डेटा को आंशिक रूप से पास करने की अनुमति देती है, बस दूसरे तर्क के रूप में डेटा की एक सरणी को पारित करना।
<?php $this->partial('partials/content', array('greeting' => 'Welcome!')) ?>
डिफ़ॉल्ट रूप से, पैरिअल्स के पास मूल विषय में उपलब्ध डेटा तक पहुंच है और डेटा एक्सप्लिसिटी पास है।
यदि आंशिक रूप से पारित होने वाले कुछ चर में मूल विषय चर का समान नाम होता है, तो चर स्पष्ट रूप से पारित हो जाता है।
हालाँकि, आंशिक रूप से पृथक मोड में आंशिक रूप से शामिल करना संभव है, अर्थात आंशिक में मूल विषय डेटा तक पहुंच नहीं है। ऐसा करने के लिए, बस true
तीसरे तर्क के रूप में पास करें partial()
:
<?php $this->partial('partials/content', array('greeting' => 'Welcome!'), true) ?>
निष्कर्ष
भले ही बहुत सरल है, Engine
वर्ग बहुत पूरा है, लेकिन निश्चित रूप से आगे सुधार किया जा सकता है। जैसे चर को परिभाषित किया गया है या नहीं यह जांचने का कोई तरीका नहीं है।
वर्डप्रेस सुविधाओं और टेम्पलेट पदानुक्रम के साथ इसकी 100% संगतता के लिए धन्यवाद आप इसे मौजूदा और तीसरे पक्ष के कोड के साथ एकीकृत कर सकते हैं जिसमें कोई समस्या नहीं है।
हालांकि, ध्यान दें कि केवल आंशिक रूप से परीक्षण किया गया है, इसलिए संभव है कि ऐसे मुद्दे हैं जिन्हें मैंने अभी तक नहीं खोजा है।
के तहत पांच अंक "हम क्या हासिल किया?" में @kaiser जवाब :
- आसानी से डेटा संरचना को बदलने के बिना टेम्पलेट्स का आदान-प्रदान करें
- टेंपरेचर पढ़ना आसान है
- वैश्विक दायरे से बचें
- यूनिट-टेस्ट कर सकते हैं
- अन्य घटकों को नुकसान पहुँचाए बिना मॉडल / डेटा का आदान-प्रदान कर सकते हैं
मेरी कक्षा के लिए भी सभी मान्य हैं।