pre_get_posts
সত্য পৃষ্ঠাগুলি এবং স্থিতিশীল সম্মুখ পৃষ্ঠাগুলিতে কীভাবে ব্যবহার করা যায় সে সম্পর্কে আমি যথেষ্ট বিস্তৃত গবেষণা করেছি এবং মনে হয় কোনও বোকা প্রমাণ পদ্ধতি নেই।
আমি আজ অবধি সবচেয়ে ভাল বিকল্পটি পেয়েছি স্ট্যাকওভারফ্লোতে @ বিবারগায়ার দ্বারা পোস্ট করা । আমি এটিকে একটি ডেমো ক্লাসে আবার লিখেছি এবং কোডটি কিছুটা গতিশীল করেছি
class PreGeTPostsForPages
{
/**
* @var string|int $pageID
* @access protected
* @since 1.0.0
*/
protected $pageID;
/**
* @var bool $injectPageIntoLoop
* @access protected
* @since 1.0.0
*/
protected $injectPageIntoLoop;
/**
* @var array $args
* @access protected
* @since 1.0.0
*/
protected $args;
/**
* @var int $validatedPageID
* @access protected
* @since 1.0.0
*/
protected $validatedPageID = 0;
/**
* Constructor
*
* @param string|int $pageID = NULL
* @param bool $injectPageIntoLoop = false
* @param array| $args = []
* @since 1.0.0
*/
public function __construct(
$pageID = NULL,
$injectPageIntoLoop = true,
$args = []
) {
$this->pageID = $pageID;
$this->injectPageIntoLoop = $injectPageIntoLoop;
$this->args = $args;
}
/**
* Private method validatePageID()
*
* Validates the page ID passed
*
* @since 1.0.0
*/
private function validatePageID()
{
$validatedPageID = filter_var( $this->pageID, FILTER_VALIDATE_INT );
$this->validatedPageID = $validatedPageID;
}
/**
* Public method init()
*
* This method is used to initialize our pre_get_posts action
*
* @since 1.0.0
*/
public function init()
{
// Load the correct actions according to the value of $this->keepPageIntegrity
add_action( 'pre_get_posts', [$this, 'preGetPosts'] );
}
/**
* Protected method pageObject()
*
* Gets the queried object to use that as page object
*
* @since 1.0.0
*/
protected function pageObject()
{
global $wp_the_query;
return $wp_the_query->get_queried_object();
}
/**
* Public method preGetPosts()
*
* This is our call back method for the pre_get_posts action.
*
* The pre_get_posts action will only be used if the page integrity is
* not an issue, which means that the page will be altered to work like a
* normal archive page. Here you have the option to inject the page object as
* first post through the_posts filter when $this->injectPageIntoLoop === true
*
* @since 1.0.0
*/
public function preGetPosts( \WP_Query $q )
{
// Make sure that we are on the main query and the desired page
if ( is_admin() // Only run this on the front end
|| !$q->is_main_query() // Only target the main query
|| !is_page( $this->validatedPageID ) // Run this only on the page specified
)
return;
// Remove the filter to avoid infinte loops
remove_filter( current_filter(), [$this, __METHOD__] );
// METHODS:
$this->validatePageID();
$this->pageObject();
$queryArgs = $this->args;
// Set default arguments which cannot be changed
$queryArgs['pagename'] = NULL;
// We have reached this point, lets do what we need to do
foreach ( $queryArgs as $key=>$value )
$q->set(
filter_var( $key, FILTER_SANITIZE_STRING ),
$value // Let WP_Query handle the sanitation of the values accordingly
);
// Set $q->is_singular to 0 to get pagination to work
$q->is_singular = false;
// FILTERS:
add_filter( 'the_posts', [$this, 'addPageAsPost'], PHP_INT_MAX );
add_filter( 'template_include', [$this, 'templateInclude'], PHP_INT_MAX );
}
/**
* Public callback method hooked to 'the_posts' filter
* This will inject the queried object into the array of posts
* if $this->injectPageIntoLoop === true
*
* @since 1.0.0
*/
public function addPageAsPost( $posts )
{
// Inject the page object as a post if $this->injectPageIntoLoop == true
if ( true === $this->injectPageIntoLoop )
return array_merge( [$this->pageObject()], $posts );
return $posts;
}
/**
* Public call back method templateInclude() for the template_include filter
*
* @since 1.0.0
*/
public function templateInclude( $template )
{
// Remove the filter to avoid infinte loops
remove_filter( current_filter(), [$this, __METHOD__] );
// Get the page template saved in db
$pageTemplate = get_post_meta(
$this->validatedPageID,
'_wp_page_template',
true
);
// Make sure the template exists before we load it, but only if $template is not 'default'
if ( 'default' !== $pageTemplate ) {
$locateTemplate = locate_template( $pageTemplate );
if ( $locateTemplate )
return $template = $locateTemplate;
}
/**
* If $template returned 'default', or the template is not located for some reason,
* we need to get and load the template according to template hierarchy
*
* @uses get_page_template()
*/
return $template = get_page_template();
}
}
$init = new PreGeTPostsForPages(
251, // Page ID
false,
[
'posts_per_page' => 3,
'post_type' => 'post'
]
);
$init->init();
এটি আমার নিজের পৃষ্ঠার ফাংশনটি ব্যবহার করে প্রত্যাশার মতো ভাল এবং পৃষ্ঠায় কাজ করে ।
সমস্যা:
ফাংশনটির কারণে, আমি পৃষ্ঠা অখণ্ডতা looseিলে করে রাখি যা সঞ্চিত পৃষ্ঠায় থাকা সামগ্রীতে অন্যান্য ফাংশন নির্ভর করে $post
। $post
লুপটি লুপের প্রথম পোস্টে সেট করার আগে এবং লুপের $post
পরে লুপের শেষ পোস্টে সেট করার আগে, যা প্রত্যাশিত। আমার যা দরকার তা হ'ল $post
এটি বর্তমান পৃষ্ঠার বস্তুতে, যেমন কোয়েরি অবজেক্টে সেট করা আছে।
এছাড়াও, $wp_the_query->post
এবং $wp_query->post
লুপে প্রথম পোস্ট ধারণ করে এবং সাধারণ পৃষ্ঠায় কোয়েরি করা বস্তুটি নয়
লুপের আগে এবং পরে আমার গ্লোবালগুলি পরীক্ষা করতে আমি নীচেরগুলি ( আমার শ্রেণীর বাইরে ) ব্যবহার করি
add_action( 'wp_head', 'printGlobals' );
add_action( 'wp_footer', 'printGlobals' );
function printGlobals()
{
$global_test = 'QUERIED OBJECT: ' . $GLOBALS['wp_the_query']->queried_object_id . '</br>';
$global_test .= 'WP_THE_QUERY: ' . $GLOBALS['wp_the_query']->post->ID . '</br>';
$global_test .= 'WP_QUERY: ' . $GLOBALS['wp_query']->post->ID . '</br>';
$global_test .= 'POST: ' . $GLOBALS['post']->ID . '</br>';
$global_test .= 'FOUND_POSTS: ' . $GLOBALS['wp_query']->found_posts . '</br>';
$global_test .= 'MAX_NUM_PAGES: ' . $GLOBALS['wp_query']->max_num_pages . '</br>';
?><pre><?php var_dump( $global_test ); ?></pre><?php
}
লুপের আগে:
লুপের আগে, সমস্যাটি আংশিকভাবে ঠিক করে সেট $injectPageIntoLoop
করে সমাধান করা হয় যা পৃষ্ঠা অবজেক্টটিকে লুপের প্রথম পৃষ্ঠা হিসাবে ইনজেক্ট করে। অনুরোধকৃত পোস্টগুলির আগে আপনার যদি পৃষ্ঠার তথ্যটি দেখানোর দরকার হয় তবে এটি বেশ কার্যকর but
আমি গ্লোবালগুলি সরাসরি হ্যাক করে লুপের আগে বিষয়টি সমাধান করতে পারি, যা আমি সত্যিই পছন্দ করি না। আমি wp
আমার preGetPosts
পদ্ধতির অভ্যন্তরে নিম্নলিখিত পদ্ধতিটি হুক করেছি
public function wp()
{
$page = get_post( $this->pageID );
$GLOBALS['wp_the_query']->post = $page;
$GLOBALS['wp_query'] = $GLOBALS['wp_the_query'];
$GLOBALS['post'] = $page;
}
এবং ভিতরে preGetPosts
পদ্ধতি
add_action( 'wp', [$this, 'wp'] );
এই থেকে, $wp_the_query->post
, $wp_query->post
এবং $post
সব ঝুলিতে পৃষ্ঠা অবজেক্ট।
লুপের পরে
লুপের পরে এখানে আমার বড় সমস্যা। wp
হুক এবং পদ্ধতির মাধ্যমে গ্লোবালগুলি হ্যাক করার পরে ,
$wp_the_query->post
এবং$wp_query->post
লুপ প্রথম পোস্ট সেট ফিরে, আশানুরূপ$post
লুপে সর্বশেষ পোস্টে সেট করা আছে।
আমার যা দরকার তা হল তিনটিই আবার কোয়েরি অবজেক্ট / বর্তমান পৃষ্ঠা অবজেক্টে সেট করা আছে to
আমি wp
পদ্ধতিটিতে loop_end
পদক্ষেপের চেষ্টা করেছি , যা কার্যকর হয় না। Hooking wp
করার পদ্ধতি get_sidebar
কর্ম কাজ করে, কিন্তু খুব দেরি হয়ে গেছে।
add_action( 'get_sidebar', [$this, 'wp'] );
চলমান printGlobals()
টেমপ্লেট নিশ্চিত করে যে হিসাবে লুপ পর সরাসরি $wp_the_query->post
এবং $wp_query->post
এখনও প্রথম পোস্টে এবং নির্ধারণ করা হয় $post
গত পোস্টে।
আমি ম্যানুয়ালি wp
টেমপ্লেটের অভ্যন্তরে লুপের পরে পদ্ধতির অভ্যন্তরে কোডটি যুক্ত করতে পারি , তবে ধারণাটি টেমপ্লেটের ফাইলগুলিকে সরাসরি পরিবর্তন করার নয় কারণ ক্লাসটি থিমগুলির মধ্যে একটি প্লাগইনে স্থানান্তরযোগ্য হতে হবে।
এই সমস্যাটি সমাধান করার কোনও সঠিক উপায় আছে যেখানে pre_get_posts
সত্যিকারের পৃষ্ঠায় এবং স্থির সম্মুখ পৃষ্ঠায় চলে এবং এখনও এর অখণ্ডতা বজায় থাকে $wp_the_query->post
,$wp_query->post
এবং $post
( জানতে চাওয়া বস্তু ঐ সেট থাকার আগে ও লুপ পর)।
সম্পাদনা
আমার কী প্রয়োজন এবং কেন আমার এটি প্রয়োজন তা নিয়ে বিভ্রান্তি দেখা দিয়েছে
আমার যা দরকার
আমার মূল্যবোধ ধরে রাখতে হবে $wp_the_query->post
, $wp_query->post
এবং$post
নির্বিশেষে টেমপ্লেট জুড়ে, এবং যে মান জানতে চাওয়া বস্তুর হওয়া উচিত। এই পর্যায়ে, আমি পোস্ট করা কোড সহ, এই তিনটি ভেরিয়েবলের মানগুলি পৃষ্ঠা অবজেক্টটিকে ধরে রাখে না, বরং লুপে পোস্টের অবজেক্ট পোস্ট করে। আমি আশা করি এটি যথেষ্ট পরিষ্কার।
আমি কোড পোস্ট করেছি যা আপনি এই ভেরিয়েবলগুলি পরীক্ষা করতে ব্যবহার করতে পারেন
আমার কেন এটি দরকার
pre_get_posts
পুরো পৃষ্ঠার কার্যকারিতা পরিবর্তন না করে পৃষ্ঠার টেম্পলেট এবং স্থির সম্মুখ পৃষ্ঠাগুলির মাধ্যমে পোস্ট যুক্ত করার জন্য আমার একটি নির্ভরযোগ্য উপায় প্রয়োজন need এই পর্যায়ে, প্রশ্নের কোডটি দাঁড় করায়, এটি আমার রুটির ক্র্যাম্ব বৈশিষ্ট্যটি এবং লুপের পরে সম্পর্কিত পৃষ্ঠা বৈশিষ্ট্যটি ভেঙে দেয় $post
যার "ভুল" পোস্ট অবজেক্ট রয়েছে।
সর্বোপরি, আমি পৃষ্ঠার টেম্পলেটগুলি সরাসরি পরিবর্তন করতে চাই না। আমি টেমপ্লেটে কোনও পরিবর্তন ছাড়াই কোনও পৃষ্ঠা টেম্পলেটে পোস্ট যুক্ত করতে সক্ষম হতে চাই