जब आप एक दृश्य पृष्ठ पर जाते हैं, तो वर्डप्रेस डेटाबेस को क्वेरी करेगा और यदि आपका पेज डेटाबेस में मौजूद नहीं है, तो उस क्वेरी की आवश्यकता नहीं है और यह केवल संसाधनों की बर्बादी है।
सौभाग्य से, वर्डप्रेस कस्टम तरीके से फ्रंटेंड अनुरोधों को संभालने का एक तरीका प्रदान करता है। यह 'do_parse_request'
फिल्टर के लिए धन्यवाद किया जाता है ।
false
उस हुक पर वापस लौटने पर, आप वर्डप्रेस को प्रसंस्करण अनुरोधों से रोकने में सक्षम होंगे और इसे अपने कस्टम तरीके से कर सकते हैं।
उस ने कहा, मैं एक साधारण ओओपी प्लगइन बनाने का एक तरीका साझा करना चाहता हूं जो आभासी पृष्ठों को उपयोग करने के लिए आसान (और पुनः उपयोग) तरीके से संभाल सकता है।
हमें क्या चाहिये
- वर्चुअल पेज ऑब्जेक्ट के लिए एक क्लास
- एक नियंत्रक वर्ग, जो एक अनुरोध को देखेगा और यदि यह एक आभासी पृष्ठ के लिए है, तो इसे उचित टेम्पलेट का उपयोग करके दिखाएं
- टेम्पलेट लोड करने के लिए एक वर्ग
- मुख्य प्लगइन फ़ाइलें हुक जोड़ने के लिए जो सब कुछ काम कर देगा
इंटरफेस
कक्षाएं बनाने से पहले, ऊपर सूचीबद्ध 3 ऑब्जेक्ट के लिए इंटरफेस लिखें।
पहला पेज इंटरफ़ेस (फ़ाइल PageInterface.php
):
<?php
namespace GM\VirtualPages;
interface PageInterface {
function getUrl();
function getTemplate();
function getTitle();
function setTitle( $title );
function setContent( $content );
function setTemplate( $template );
/**
* Get a WP_Post build using virtual Page object
*
* @return \WP_Post
*/
function asWpPost();
}
अधिकांश विधियां सिर्फ गेटर्स और सेटर हैं, स्पष्टीकरण की कोई आवश्यकता नहीं है। WP_Post
वर्चुअल पेज से ऑब्जेक्ट प्राप्त करने के लिए अंतिम विधि का उपयोग किया जाना चाहिए ।
नियंत्रक इंटरफ़ेस (फ़ाइल ControllerInterface.php
):
<?php
namespace GM\VirtualPages;
interface ControllerInterface {
/**
* Init the controller, fires the hook that allows consumer to add pages
*/
function init();
/**
* Register a page object in the controller
*
* @param \GM\VirtualPages\Page $page
* @return \GM\VirtualPages\Page
*/
function addPage( PageInterface $page );
/**
* Run on 'do_parse_request' and if the request is for one of the registered pages
* setup global variables, fire core hooks, requires page template and exit.
*
* @param boolean $bool The boolean flag value passed by 'do_parse_request'
* @param \WP $wp The global wp object passed by 'do_parse_request'
*/
function dispatch( $bool, \WP $wp );
}
और टेम्पलेट लोडर इंटरफ़ेस (फ़ाइल TemplateLoaderInterface.php
):
<?php
namespace GM\VirtualPages;
interface TemplateLoaderInterface {
/**
* Setup loader for a page objects
*
* @param \GM\VirtualPagesPageInterface $page matched virtual page
*/
public function init( PageInterface $page );
/**
* Trigger core and custom hooks to filter templates,
* then load the found template.
*/
public function load();
}
इन इंटरफेस के लिए phpDoc टिप्पणियाँ बहुत स्पष्ट होनी चाहिए।
योजना
अब जब हमारे पास इंटरफेस है, और कंक्रीट कक्षाएं लिखने से पहले, हम अपने वर्कफ़्लो की समीक्षा करें:
- पहले हम एक
Controller
कक्षा को लागू करते हैं (लागू करते हैं ControllerInterface
) और इंजेक्ट करते हैं (शायद एक कंस्ट्रक्टर में) TemplateLoader
कक्षा का एक उदाहरण (कार्यान्वयन TemplateLoaderInterface
)
- पर
init
हुक हम फोन ControllerInterface::init()
सेटअप करने के लिए विधि नियंत्रक और हुक है कि उपभोक्ता कोड आभासी पृष्ठों को जोड़ने के लिए प्रयोग करेंगे आग।
- पर 'do_parse_request' हम फोन करेगा
ControllerInterface::dispatch()
, और वहाँ हम सब आभासी पृष्ठ जोड़ की जाँच करेगा और अगर उनमें से एक वर्तमान अनुरोध के समान URL है, यह प्रदर्शित करती हैं; सभी मुख्य वैश्विक चर ( $wp_query
, $post
) सेट करने के बाद । हम TemplateLoader
सही टेम्पलेट को लोड करने के लिए क्लास का भी उपयोग करेंगे ।
इस दौरान कार्यप्रवाह हम ट्रिगर किया जाएगा कुछ कोर हुक, जैसे wp
, template_redirect
,template_include
... प्लगइन अधिक लचीला बनाने और कोर और अन्य प्लग-इन, या उनमें से एक अच्छी संख्या के साथ कम से कम के साथ संगतता सुनिश्चित करने के लिए।
पिछले वर्कफ़्लो के अलावा, हमें यह भी करना होगा:
- मुख्य लूप चलने के बाद हुक और वैश्विक चर को साफ करें, फिर से कोर और 3 पार्टी कोड के साथ संगतता में सुधार करने के लिए
the_permalink
जरूरत पड़ने पर सही वर्चुअल पेज URL को वापस करने के लिए एक फ़िल्टर जोड़ें ।
कंक्रीट कक्षाएं
अब हम अपने ठोस वर्गों को कोड कर सकते हैं। पेज क्लास (फाइल Page.php
) से शुरू करते हैं :
<?php
namespace GM\VirtualPages;
class Page implements PageInterface {
private $url;
private $title;
private $content;
private $template;
private $wp_post;
function __construct( $url, $title = 'Untitled', $template = 'page.php' ) {
$this->url = filter_var( $url, FILTER_SANITIZE_URL );
$this->setTitle( $title );
$this->setTemplate( $template);
}
function getUrl() {
return $this->url;
}
function getTemplate() {
return $this->template;
}
function getTitle() {
return $this->title;
}
function setTitle( $title ) {
$this->title = filter_var( $title, FILTER_SANITIZE_STRING );
return $this;
}
function setContent( $content ) {
$this->content = $content;
return $this;
}
function setTemplate( $template ) {
$this->template = $template;
return $this;
}
function asWpPost() {
if ( is_null( $this->wp_post ) ) {
$post = array(
'ID' => 0,
'post_title' => $this->title,
'post_name' => sanitize_title( $this->title ),
'post_content' => $this->content ? : '',
'post_excerpt' => '',
'post_parent' => 0,
'menu_order' => 0,
'post_type' => 'page',
'post_status' => 'publish',
'comment_status' => 'closed',
'ping_status' => 'closed',
'comment_count' => 0,
'post_password' => '',
'to_ping' => '',
'pinged' => '',
'guid' => home_url( $this->getUrl() ),
'post_date' => current_time( 'mysql' ),
'post_date_gmt' => current_time( 'mysql', 1 ),
'post_author' => is_user_logged_in() ? get_current_user_id() : 0,
'is_virtual' => TRUE,
'filter' => 'raw'
);
$this->wp_post = new \WP_Post( (object) $post );
}
return $this->wp_post;
}
}
इंटरफ़ेस को लागू करने से ज्यादा कुछ नहीं।
अब नियंत्रक वर्ग (फ़ाइल Controller.php
):
<?php
namespace GM\VirtualPages;
class Controller implements ControllerInterface {
private $pages;
private $loader;
private $matched;
function __construct( TemplateLoaderInterface $loader ) {
$this->pages = new \SplObjectStorage;
$this->loader = $loader;
}
function init() {
do_action( 'gm_virtual_pages', $this );
}
function addPage( PageInterface $page ) {
$this->pages->attach( $page );
return $page;
}
function dispatch( $bool, \WP $wp ) {
if ( $this->checkRequest() && $this->matched instanceof Page ) {
$this->loader->init( $this->matched );
$wp->virtual_page = $this->matched;
do_action( 'parse_request', $wp );
$this->setupQuery();
do_action( 'wp', $wp );
$this->loader->load();
$this->handleExit();
}
return $bool;
}
private function checkRequest() {
$this->pages->rewind();
$path = trim( $this->getPathInfo(), '/' );
while( $this->pages->valid() ) {
if ( trim( $this->pages->current()->getUrl(), '/' ) === $path ) {
$this->matched = $this->pages->current();
return TRUE;
}
$this->pages->next();
}
}
private function getPathInfo() {
$home_path = parse_url( home_url(), PHP_URL_PATH );
return preg_replace( "#^/?{$home_path}/#", '/', esc_url( add_query_arg(array()) ) );
}
private function setupQuery() {
global $wp_query;
$wp_query->init();
$wp_query->is_page = TRUE;
$wp_query->is_singular = TRUE;
$wp_query->is_home = FALSE;
$wp_query->found_posts = 1;
$wp_query->post_count = 1;
$wp_query->max_num_pages = 1;
$posts = (array) apply_filters(
'the_posts', array( $this->matched->asWpPost() ), $wp_query
);
$post = $posts[0];
$wp_query->posts = $posts;
$wp_query->post = $post;
$wp_query->queried_object = $post;
$GLOBALS['post'] = $post;
$wp_query->virtual_page = $post instanceof \WP_Post && isset( $post->is_virtual )
? $this->matched
: NULL;
}
public function handleExit() {
exit();
}
}
अनिवार्य रूप से वर्ग ए बनाता है SplObjectStorage
ऑब्जेक्ट जहां सभी जोड़े गए पृष्ठ ऑब्जेक्ट संग्रहीत होते हैं।
पर 'do_parse_request'
, नियंत्रक वर्ग जोड़े गए पृष्ठों में से एक में वर्तमान URL के लिए एक मैच खोजने के लिए इस स्टोरेज को लूप करता है।
यदि यह पाया जाता है, तो क्लास बिल्कुल वही करता है जो हमने योजना बनाई थी: कुछ हुक ट्रिगर करें, सेटअप वेरिएबल और टेम्प्लेट को क्लास के माध्यम से लोड करें TemplateLoaderInterface
। उसके बाद, बस exit()
।
तो चलिए लिखते हैं आखिरी क्लास:
<?php
namespace GM\VirtualPages;
class TemplateLoader implements TemplateLoaderInterface {
public function init( PageInterface $page ) {
$this->templates = wp_parse_args(
array( 'page.php', 'index.php' ), (array) $page->getTemplate()
);
}
public function load() {
do_action( 'template_redirect' );
$template = locate_template( array_filter( $this->templates ) );
$filtered = apply_filters( 'template_include',
apply_filters( 'virtual_page_template', $template )
);
if ( empty( $filtered ) || file_exists( $filtered ) ) {
$template = $filtered;
}
if ( ! empty( $template ) && file_exists( $template ) ) {
require_once $template;
}
}
}
वर्चुअल पेज में संग्रहीत टेम्प्लेट को डिफ़ॉल्ट में सरणी में मर्ज कर दिया जाता है page.php
और index.php
, टेम्प्लेट लोड करने से पहले 'template_redirect'
, लचीलापन जोड़ने और संगतता में सुधार करने के लिए।
उसके बाद, पाया गया टेम्पलेट कस्टम 'virtual_page_template'
और कोर 'template_include'
फिल्टर से गुजरता है : फिर से लचीलापन और संगतता के लिए।
अंत में टेम्पलेट फ़ाइल बस भरी हुई है।
मुख्य प्लगइन फ़ाइल
इस बिंदु पर हमें प्लगइन हेडर के साथ फाइल लिखने की जरूरत है और इसे जोड़ने के लिए हुक का उपयोग करें जो हमारे वर्कफ़्लो को बना देगा:
<?php namespace GM\VirtualPages;
/*
Plugin Name: GM Virtual Pages
*/
require_once 'PageInterface.php';
require_once 'ControllerInterface.php';
require_once 'TemplateLoaderInterface.php';
require_once 'Page.php';
require_once 'Controller.php';
require_once 'TemplateLoader.php';
$controller = new Controller ( new TemplateLoader );
add_action( 'init', array( $controller, 'init' ) );
add_filter( 'do_parse_request', array( $controller, 'dispatch' ), PHP_INT_MAX, 2 );
add_action( 'loop_end', function( \WP_Query $query ) {
if ( isset( $query->virtual_page ) && ! empty( $query->virtual_page ) ) {
$query->virtual_page = NULL;
}
} );
add_filter( 'the_permalink', function( $plink ) {
global $post, $wp_query;
if (
$wp_query->is_page && isset( $wp_query->virtual_page )
&& $wp_query->virtual_page instanceof Page
&& isset( $post->is_virtual ) && $post->is_virtual
) {
$plink = home_url( $wp_query->virtual_page->getUrl() );
}
return $plink;
} );
वास्तविक फ़ाइल में हम शायद अधिक हेडर जोड़ेंगे, जैसे प्लगइन और लेखक लिंक, विवरण, लाइसेंस, आदि।
प्लगिन जिस्ट
ठीक है, हम अपने प्लगइन के साथ किया जाता है। सभी कोड यहां एक जिस्ट में मिल सकते हैं ।
पेज जोड़ना
प्लगइन तैयार है और काम कर रहा है, लेकिन हमने कोई पृष्ठ नहीं जोड़ा है।
कि प्लगइन के अंदर ही किया जा सकता है, अंदर विषय functions.php
, एक अन्य प्लगइन में, आदि।
पृष्ठों को जोड़ना केवल एक बात है:
<?php
add_action( 'gm_virtual_pages', function( $controller ) {
// first page
$controller->addPage( new \GM\VirtualPages\Page( '/custom/page' ) )
->setTitle( 'My First Custom Page' )
->setTemplate( 'custom-page-form.php' );
// second page
$controller->addPage( new \GM\VirtualPages\Page( '/custom/page/deep' ) )
->setTitle( 'My Second Custom Page' )
->setTemplate( 'custom-page-deep.php' );
} );
और इसी तरह। आप अपनी ज़रूरत के सभी पेज जोड़ सकते हैं, बस पृष्ठों के लिए सापेक्ष URL का उपयोग करना याद रखें।
टेम्प्लेट फ़ाइल के अंदर आप सभी वर्डप्रेस टेम्प्लेट टैग का उपयोग कर सकते हैं, और आप अपनी ज़रूरत के सभी पीएचपी और एचटीएमएल लिख सकते हैं।
वैश्विक पोस्ट ऑब्जेक्ट हमारे वर्चुअल पेज से आने वाले डेटा से भरा है। वर्चुअल पेज को ही $wp_query->virtual_page
वेरिएबल के जरिए एक्सेस किया जा सकता है ।
वर्चुअल पेज के लिए URL प्राप्त करना उतना ही आसान है जितना home_url()
कि पेज बनाने के लिए उसी पथ पर जाना:
$custom_page_url = home_url( '/custom/page' );
ध्यान दें कि लोड किए गए टेम्पलेट में मुख्य लूप में, the_permalink()
वर्चुअल पेज पर सही पर्मलिंक लौटाएगा।
आभासी पृष्ठों के लिए शैलियों / लिपियों पर नोट्स
संभवतया जब वर्चुअल पेज जोड़े जाते हैं, तो कस्टम स्टाइल / स्क्रिप्ट्स को संलग्न करना और फिर wp_head()
कस्टम टेम्पलेट में उपयोग करना भी वांछनीय है ।
यह बहुत आसान है, क्योंकि वर्चुअल पेज आसानी से $wp_query->virtual_page
वेरिएबल को देखते हुए पहचाने जाते हैं और वर्चुअल पेज अपने URL को देखने वाले से अलग पहचाने जा सकते हैं।
बस एक उदाहरण:
add_action( 'wp_enqueue_scripts', function() {
global $wp_query;
if (
is_page()
&& isset( $wp_query->virtual_page )
&& $wp_query->virtual_page instanceof \GM\VirtualPages\PageInterface
) {
$url = $wp_query->virtual_page->getUrl();
switch ( $url ) {
case '/custom/page' :
wp_enqueue_script( 'a_script', $a_script_url );
wp_enqueue_style( 'a_style', $a_style_url );
break;
case '/custom/page/deep' :
wp_enqueue_script( 'another_script', $another_script_url );
wp_enqueue_style( 'another_style', $another_style_url );
break;
}
}
} );
ओपी को नोट्स
एक पृष्ठ से दूसरे में डेटा पास करना इन आभासी पृष्ठों से संबंधित नहीं है, लेकिन यह केवल एक सामान्य कार्य है।
हालाँकि, यदि आपके पास पहले पृष्ठ में एक फॉर्म है, और वहाँ से डेटा को दूसरे पेज पर भेजना चाहते हैं, तो बस फॉर्म में दूसरे पेज के URL का उपयोग action
प्रॉपर्टी के रूप में करें।
पहले पृष्ठ टेम्पलेट फ़ाइल में आप कर सकते हैं:
<form action="<?php echo home_url( '/custom/page/deep' ); ?>" method="POST">
<input type="text" name="testme">
</form>
और फिर दूसरे पेज टेम्पलेट फ़ाइल में:
<?php $testme = filter_input( INPUT_POST, 'testme', FILTER_SANITIZE_STRING ); ?>
<h1>Test-Me value form other page is: <?php echo $testme; ?></h1>