কখন WP_query (), ক্যোয়ারী_পোস্টগুলি () এবং প্রাক_জেট_পোস্টগুলি ব্যবহার করবেন


159

আমি @ নাকিন'স পড়েছি আপনি গতকাল ক্যোরি জানেন না এবং কিছুটা জিজ্ঞাসা করা খরগোশের গর্ত থেকে তাকে নামিয়ে দেওয়া হয়েছিল। গতকালের আগে আমি (ভুলভাবে) query_posts()আমার সমস্ত অনুসন্ধানের প্রয়োজনে ব্যবহার করছিলাম। এখন আমি ব্যবহার সম্পর্কে কিছুটা বুদ্ধিমান WP_Query(), তবে এখনও কিছু ধূসর অঞ্চল রয়েছে।

আমি যা মনে করি আমি নিশ্চিতভাবে জানি:

আমি তৈরি করছি যদি অতিরিক্ত যেকোনো জায়গায় লুপ একটি পৃষ্ঠায়-ইন পার্শ্বদন্ডে, একটি ফুটার মধ্যে, "সম্পর্কিত পোস্ট", যে কোন ধরণের ইত্যাদি-আমি ব্যবহার করতে চান WP_Query()। আমি কোনও ক্ষতি ছাড়াই একক পৃষ্ঠায় বারবার এটি ব্যবহার করতে পারি। (ডান?)।

আমি যা নিশ্চিত তা জানি না

  1. আমি কখন @ ন্যাসিনের pre_get_posts বনাম ব্যবহার করব WP_Query()? আমার pre_get_postsকি এখন সব কিছুর জন্য ব্যবহার করা উচিত ?
  2. যখন আমি কোনও টেমপ্লেট পৃষ্ঠায় লুপটি সংশোধন করতে চাই - আসুন আমি বলি যে আমি একটি করশাসন সংরক্ষণাগার পৃষ্ঠার সংশোধন করতে চাই - আমি কি if have_posts : while have_posts : the_postঅংশটি সরিয়ে আমার নিজের লিখতে চাই WP_Query()? বা আমি pre_get_postsআমার ফাংশন.এফপি ফাইল ব্যবহার করে আউটপুট পরিবর্তন করব?

TL; ড

টিএল; ডাঃ বিধিগুলি আমি এর থেকে আঁকতে চাই:

  1. query_postsআর কখনও ব্যবহার করবেন না
  2. একক পৃষ্ঠায় একাধিক অনুসন্ধান চালানোর সময়, ব্যবহার করুন WP_Query()
  3. একটি লুপ পরিবর্তন করার সময়, এই __________________ করুন do

কোন জ্ঞানের জন্য ধন্যবাদ

টেরি

PS: আমি দেখেছি এবং পড়েছি: কখন আপনি ডাব্লুপি_কিউয়ারি বনাম কোয়েরি_পোস্টগুলি () বনাম get_posts () ব্যবহার করবেন? যা আরও একটি মাত্রা যুক্ত করে - get_posts। তবে একেবারেই ডিল করে না pre_get_posts



@ সালটকোড, এখন আলাদা, ওয়ার্ডপ্রেস বিবর্তিত, আমি এখানে গৃহীত উত্তরের তুলনায় কয়েকটি মন্তব্য যুক্ত করেছি ।
prosti থেকে

উত্তর:


145

আপনি ঠিক বলেছেন:

query_postsআর কখনও ব্যবহার করবেন না

pre_get_posts

pre_get_postsকোনও ক্যোয়ারী পরিবর্তন করার জন্য এটি একটি ফিল্টার । এটি কেবলমাত্র 'মূল ক্যোয়ারী' পরিবর্তন করতে ব্যবহৃত হয়:

add_action('pre_get_posts','wpse50761_alter_query');
function wpse50761_alter_query($query){

      if( $query->is_main_query() ){
        //Do something to main query
      }
}

(আমি এটিও খতিয়ে দেখব যে এটি is_admin()প্রত্যাখ্যান করে - যদিও এটি অতিরিক্ত কাজ হতে পারে) মূল প্রশ্নটি আপনার টেম্পলেটগুলিতে প্রদর্শিত হবে:

if( have_posts() ):
    while( have_posts() ): the_post();
       //The loop
    endwhile;
endif;

আপনি যদি কখনও এই লুপটি সম্পাদনা করার প্রয়োজন বোধ করেন - ব্যবহার করুন pre_get_posts। অর্থাত্ যদি আপনি প্ররোচিত হন query_posts()- pre_get_postsপরিবর্তে ব্যবহার করুন।

WP_Query

মূল ক্যোয়ারী একটি এর একটি গুরুত্বপূর্ণ উদাহরণ WP_Query object। ওয়ার্ডপ্রেস কোন টেম্পলেটটি ব্যবহার করবে তা সিদ্ধান্ত নিতে এটি ব্যবহার করে, উদাহরণস্বরূপ এবং ইউআরএল (যেমন পৃষ্ঠায়িতকরণ) এর মধ্যে যে কোনও যুক্তি দেওয়া হয়েছিল তা সমস্ত WP_Queryবস্তুর সেই দৃষ্টান্তে চ্যানেলযুক্ত ।

সেকেন্ডারি লুপগুলির জন্য (যেমন সাইড-বার, বা 'সম্পর্কিত পোস্ট' তালিকাগুলিতে) আপনি WP_Queryঅবজেক্টটির নিজস্ব পৃথক উদাহরণ তৈরি করতে চাইবেন । যেমন

$my_secondary_loop = new WP_Query(...);
if( $my_secondary_loop->have_posts() ):
    while( $my_secondary_loop->have_posts() ): $my_secondary_loop->the_post();
       //The secondary loop
    endwhile;
endif;
wp_reset_postdata();

বিজ্ঞপ্তি wp_reset_postdata();- এটি কারণ সেকেন্ডারি লুপটি গ্লোবাল $postভেরিয়েবলকে ওভাররাইড করবে যা 'বর্তমান পোস্ট' সনাক্ত করে। এটি মূলত $postআমাদের সাথে চলছে তা পুনরায় সেট করে।

get_posts ()

এটি কোনও WP_Queryবস্তুর পৃথক উদাহরণের জন্য মূলত একটি মোড়ক । এটি পোস্ট অবজেক্টের একটি অ্যারে প্রদান করে। উপরের লুপে ব্যবহৃত পদ্ধতিগুলি আপনার জন্য আর উপলব্ধ নেই। এটি কোনও 'লুপ' নয়, কেবল পোস্ট অবজেক্টের একটি অ্যারে।

<ul>
<?php
global $post;
$args = array( 'numberposts' => 5, 'offset'=> 1, 'category' => 1 );
$myposts = get_posts( $args );
foreach( $myposts as $post ) :  setup_postdata($post); ?>
    <li><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
<?php endforeach; wp_reset_postdata(); ?>
</ul>

আপনার প্রশ্নের জবাবে

  1. pre_get_postsআপনার মূল ক্যোয়ারী পরিবর্তন করতে ব্যবহার করুন । WP_Queryটেমপ্লেট পৃষ্ঠাগুলিতে মাধ্যমিক লুপগুলির জন্য একটি পৃথক অবজেক্ট (পদ্ধতি 2) ব্যবহার করুন।
  2. আপনি যদি মূল লুপের ক্যোয়ারী পরিবর্তন করতে চান তবে ব্যবহার করুন pre_get_posts

তাহলে কি এমন দৃশ্য আছে যখন ডাব্লুপি_কিউয়ের পরিবর্তে কেউ সরাসরি_পোস্টে () যেতে পারবে?
urok93

@ ড্রটানজ - হ্যাঁ উদাহরণস্বরূপ বলুন আপনার পৃষ্ঠাগুলি বা শীর্ষে স্টিকি পোস্টের দরকার নেই - এই উদাহরণগুলিতে get_posts()আরও দক্ষ।
স্টিফেন হ্যারিস

তবে কি এটি কোনও অতিরিক্ত ক্যোয়ারী যুক্ত করবে না যেখানে আমরা মূল ক্যোয়ারীটি সংশোধন করতে কেবল pre_get_posts সংশোধন করতে পারি?
urok93

@ ড্রটানজ - আপনি get_posts()মূল ক্যোয়ারির জন্য ব্যবহার করবেন না - এটি মাধ্যমিক অনুসন্ধানের জন্য।
স্টিফেন হ্যারিস

1
@ স্টেফেনহরিস রাইট =) আপনি যদি_পোস্টটি ব্যবহার না করে অবজেক্টে নেক্সট_পোস্ট () ব্যবহার করেন তবে আপনি বিশ্বব্যাপী ক্যোয়ারিতে পদক্ষেপ নেবেন না এবং তারপরে wp_reset_postdata ব্যবহার করার কথা মনে রাখার দরকার নেই।
প্রাইভেটর

55

লুপগুলির জন্য দুটি পৃথক প্রসঙ্গ রয়েছে:

  • মূল লুপ যা ইউআরএল অনুরোধের ভিত্তিতে ঘটে এবং টেমপ্লেটগুলি লোড হওয়ার আগে প্রক্রিয়াজাত হয়
  • টেমপ্লেট ফাইল বা অন্যথায় কল করা অন্য কোনও উপায়ে ঘটে যাওয়া মাধ্যমিক লুপগুলি

সমস্যাটি query_posts()হ'ল এটি গৌণ লুপ যা প্রধান হতে চেষ্টা করে এবং খারাপভাবে ব্যর্থ হয়। সুতরাং এটি বিদ্যমান ভুলে যান।

প্রধান লুপটি পরিবর্তন করতে To

  • ব্যবহার করবেন না query_posts()
  • চেক pre_get_postsসঙ্গে ফিল্টার ব্যবহার করুন$query->is_main_query()
  • পর্যায়ক্রমে requestফিল্টার ব্যবহার করুন (উপরে কিছুটা রুক্ষ তাই ভাল)

গৌণ লুপ চালানোর জন্য

ব্যবহার করুন new WP_Queryবা get_posts()যা বেশ পরিমাণে বিনিময়যোগ্য (পূর্ববর্তীগুলির জন্য পাতলা মোড়ক)।

পরিস্কার কর

wp_reset_query()আপনি যদি সরাসরি query_posts()বিশ্বব্যাপী ব্যবহার করেন বা গোলযোগ পেয়ে থাকেন তবে ব্যবহার করুন $wp_query- যাতে আপনার প্রায় কখনও প্রয়োজন হয় না।

wp_reset_postdata()আপনি যদি ব্যবহার করেন the_post()বা setup_postdata()বিশ্বব্যাপী গোলযোগ করেছেন $postএবং পোস্ট সম্পর্কিত বিষয়গুলির প্রাথমিক অবস্থা পুনরুদ্ধার করতে চান তবে ব্যবহার করুন ।


3
বিরল বলতে বোঝায়wp_reset_postdata()
গ্রেগরি

23

ব্যবহারের জন্য বৈধ পরিস্থিতিতে রয়েছে query_posts($query), উদাহরণস্বরূপ:

  1. আপনি কোনও পৃষ্ঠায় পোস্টের তালিকা বা কাস্টম-পোস্ট-ধরণের পোস্ট প্রদর্শন করতে চান (একটি পৃষ্ঠা টেম্পলেট ব্যবহার করে)

  2. আপনি সেই পোস্টগুলির কাজ পৃষ্ঠাতে চান

এখন আপনি কেন সংরক্ষণাগার টেম্পলেট ব্যবহার না করে এটি কোনও পৃষ্ঠায় প্রদর্শন করতে চান?

  1. এটি প্রশাসকের পক্ষে (আপনার গ্রাহক?) আরও স্বজ্ঞাত - তারা 'পৃষ্ঠাগুলিতে' পৃষ্ঠাটি দেখতে পাবে

  2. এটিকে মেনুতে যুক্ত করার জন্য এটি আরও ভাল (পৃষ্ঠাটি ছাড়াই, তারা সরাসরি ইউআরএল যুক্ত করতে হবে)

  3. আপনি যদি টেমপ্লেটে অতিরিক্ত সামগ্রী (পাঠ্য, থাম্বনেইল পোস্ট, বা কোনও কাস্টম মেটা সামগ্রী) প্রদর্শন করতে চান তবে আপনি সহজেই পৃষ্ঠাটি থেকে এটি পেতে পারেন (এবং এটি গ্রাহকের পক্ষে আরও জ্ঞান অর্জন করে)। দেখুন আপনি কোনও সংরক্ষণাগার টেম্পলেট ব্যবহার করেছেন কিনা, আপনাকে অতিরিক্ত কন্টেন্ট হার্ডকোড করতে হবে বা থিম / প্লাগইন বিকল্পগুলির জন্য ব্যবহার করতে হবে (যা এটি গ্রাহকের পক্ষে স্বল্পতর স্বজ্ঞাত করে তোলে)

এখানে একটি সরলীকৃত উদাহরণ কোড দেওয়া হয়েছে (যা আপনার পৃষ্ঠার টেম্পলেটে থাকবে - যেমন - পৃষ্ঠা-পৃষ্ঠার-পোস্ট.পিএফপি):

/**
 * Template Name: Page of Posts
 */

while(have_posts()) { // original main loop - page content
  the_post();
  the_title(); // title of the page
  the_content(); // content of the page
  // etc...
}

// now we display list of our custom-post-type posts

// first obtain pagination parametres
$paged = 1;
if(get_query_var('paged')) {
  $paged = get_query_var('paged');
} elseif(get_query_var('page')) {
  $paged = get_query_var('page');
}

// query posts and replace the main query (page) with this one (so the pagination works)
query_posts(array('post_type' => 'my_post_type', 'post_status' => 'publish', 'paged' => $paged));

// pagination
next_posts_link();
previous_posts_link();

// loop
while(have_posts()) {
  the_post();
  the_title(); // your custom-post-type post's title
  the_content(); // // your custom-post-type post's content
}

wp_reset_query(); // sets the main query (global $wp_query) to the original page query (it obtains it from global $wp_the_query variable) and resets the post data

// So, now we can display the page-related content again (if we wish so)
while(have_posts()) { // original main loop - page content
  the_post();
  the_title(); // title of the page
  the_content(); // content of the page
  // etc...
}

এখন, পুরোপুরি পরিষ্কার করার জন্য, আমরা query_posts()এখানেও ব্যবহার এড়াতে এবং WP_Queryপরিবর্তে ব্যবহার করতে পারি - এর মতো:

// ...

global $wp_query;
$wp_query = new WP_Query(array('your query vars here')); // sets the new custom query as a main query

// your custom-post-type loop here

wp_reset_query();

// ...

কিন্তু, আমরা যখন এটির জন্য এত সুন্দর একটি ছোট্ট ফাংশন উপলব্ধ করব তখন কেন করব?


1
ব্রায়ান, তার জন্য ধন্যবাদ। আপনি যে দৃশ্যের বর্ণনা দিয়েছেন ঠিক তেমন কোনও পৃষ্ঠায় কাজ করার জন্য আমি pre_get_posts পেতে লড়াই করে যাচ্ছি: ক্লায়েন্টকে কাস্টম ক্ষেত্র / বিষয়বস্তু অন্য কোনও সংরক্ষণাগার পৃষ্ঠা হিসাবে যুক্ত করতে হবে, সুতরাং একটি "পৃষ্ঠা" তৈরি করা দরকার; ক্লায়েন্টকে ন্যাভ মেনুতে যুক্ত করার জন্য কিছু দেখার দরকার, কারণ একটি কাস্টম লিঙ্ক যুক্ত করা এগুলি পালিয়ে যায়; ইত্যাদি +1 আমার কাছ থেকে!
ল্যানি

2
এটি "pre_get_posts" ব্যবহার করেও করা যেতে পারে। আমি কাস্টম অর্ডারে এবং কাস্টম ফিল্টার সহ আমার কাস্টম পোস্ট প্রকারের তালিকাভুক্ত করার জন্য "স্ট্যাটিক ফ্রন্ট পৃষ্ঠা" রাখতে পেরেছি। এই পৃষ্ঠাটিও পৃষ্ঠাবদ্ধ রয়েছে। এটি কীভাবে কাজ করে তা দেখতে এই প্রশ্নটি পরীক্ষা করে দেখুন: wordpress.stackexchange.com/questions/30851/… সুতরাং সংক্ষেপে, ক্যোয়ারী_পোস্টগুলি ব্যবহারের জন্য আরও বৈধ পরিস্থিতি এখনও নেই;)
য় কৌবয়

1
কারণ "এটি লক্ষ করা উচিত যে এটির কোনও পৃষ্ঠায় মূল ক্যোয়ারীটি প্রতিস্থাপন করার জন্য পৃষ্ঠা লোডিংয়ের সময়গুলি বাড়ানো যেতে পারে, সবচেয়ে খারাপ ক্ষেত্রে পরিস্থিতিতে কাজের পরিমাণ দ্বিগুণ করার চেয়ে বেশি বা বেশি ব্যবহার করতে পারে use ব্যবহার সহজ হলেও, ফাংশনটিও বিভ্রান্তির ঝুঁকিতে রয়েছে এবং পরে সমস্যা। " উত্স কোডএক্স.ওয়ার্ডপ্রেস.আর.
ক্লডিউ ক্র্যাঙ্গা

এই উত্তরটি সব ধরণের ভুল। আপনি কাস্টম পোস্ট ধরণের মতো একই ইউআরএল দিয়ে ডব্লিউপিতে একটি "পৃষ্ঠা" তৈরি করতে পারেন। EG যদি আপনার সিপিটি কলা হয় তবে আপনি একই ইউআরএল দিয়ে কলা নামে একটি পৃষ্ঠা পেতে পারেন। তারপরে আপনি সাইটুরল.com/bananas দিয়ে শেষ করবেন। আপনার থিম ফোল্ডারে যতক্ষণ আপনি সংরক্ষণাগার-কলা.এফপি আছে ততক্ষণ এটি টেমপ্লেটটি ব্যবহার করবে এবং পরিবর্তে সেই পৃষ্ঠাটি "ওভাররাইড" করবে। অন্য একটি মন্তব্যে যেমন বলা হয়েছে, এই "পদ্ধতি" ব্যবহার করে ডাব্লুপিপির জন্য দ্বিগুণ কাজের চাপ তৈরি হয়, এভাবে কখনও ব্যবহার করা উচিত নয়।
হাইব্রিড ওয়েব দেব

8

আমি ফাংশন.এফপি থেকে ওয়ার্ডপ্রেস ক্যোয়ারী পরিবর্তন করেছি:

//unfortunately, "IS_PAGE" condition doesn't work in pre_get_posts (it's WORDPRESS behaviour)
//so you can use `add_filter('posts_where', ....);`    OR   modify  "PAGE" query directly into template file

add_action( 'pre_get_posts', 'myFunction' );
function myFunction($query) {
    if ( ! is_admin() && $query->is_main_query() )  {
        if (  $query->is_category ) {
            $query->set( 'post_type', array( 'post', 'page', 'my_postType' ) );
            add_filter( 'posts_where' , 'MyFilterFunction_1' ) && $GLOBALS['call_ok']=1; 
        }
    }
}
function MyFilterFunction_1($where) {
   return (empty($GLOBALS['call_ok']) || !($GLOBALS['call_ok']=false)  ? $where :  $where . " AND ({$GLOBALS['wpdb']->posts}.post_name NOT LIKE 'Journal%')"; 
}

এই উদাহরণটি দেখতে আগ্রহী হবে তবে কাস্টম মেটাতে যেখানে ধারা রয়েছে।
অ্যান্ড্রু ওয়েলচ

6

সময়ের সাথে সাথে ওয়ার্ডপ্রেস বিকশিত হওয়ায় গ্রহণযোগ্য উত্তরের কিছু উন্নয়নের রূপরেখা এবং কিছু জিনিস এখন (পাঁচ বছর পরে) আলাদা রয়েছে:

pre_get_postsকোনও ক্যোয়ারী পরিবর্তন করার জন্য এটি একটি ফিল্টার। এটি কেবলমাত্র 'মূল ক্যোয়ারী' পরিবর্তন করতে ব্যবহৃত হয়:

আসলে একটি অ্যাকশন হুক। ফিল্টার নয়, এটি কোনও প্রশ্নের উপর প্রভাব ফেলবে।

মূল প্রশ্নটি আপনার টেম্পলেটগুলিতে প্রদর্শিত হবে:

if( have_posts() ):
    while( have_posts() ): the_post();
       //The loop
    endwhile;
endif;

আসলে, এটিও সত্য নয়। ফাংশনটি কেবলমাত্র মূল ক্যোয়ারির সাথে সম্পর্কিত নয় এমন বস্তুকে have_postsপুনরাবৃত্তি করে । মাধ্যমিক প্রশ্নের সাথেও পরিবর্তন করা যেতে পারে।global $wp_queryglobal $wp_query;

function have_posts() {
    global $wp_query;
    return $wp_query->have_posts();
}

get_posts ()

এটি একটি ডাব্লুপিউকিউয়ারি আইটেমের পৃথক উদাহরণের জন্য মূলত একটি মোড়ক।

আসলে, আজকাল WP_Queryএকটি ক্লাস, তাই আমাদের একটি ক্লাসের উদাহরণ রয়েছে।


উপসংহারে: সেই সময়ে @ স্টেফেনহরিস লিখেছিলেন সম্ভবত এটি সমস্ত সত্য ছিল, তবে সময়ের সাথে সাথে ওয়ার্ডপ্রেসের জিনিসগুলি পরিবর্তিত হয়েছে।


প্রযুক্তিগতভাবে, এটি হুডের নীচে সমস্ত ফিল্টার, ক্রিয়াগুলি কেবল একটি সাধারণ ফিল্টার। তবে আপনি এখানে সঠিক, এটি এমন একটি ক্রিয়া যা রেফারেন্স দ্বারা একটি যুক্তি পাস করে, এটি কীভাবে এটি আরও সাধারণ ক্রিয়া থেকে পৃথক।
মিলো

get_postsপোস্ট অবজেক্টের একটি অ্যারে প্রদান করে, কোনও WP_Queryবস্তু নয়, তাই এটি এখনও সঠিক। এবং WP_Queryসর্বদা একটি শ্রেণি, ক্লাস = অবজেক্টের উদাহরণ।
মিলো

ধন্যবাদ, @ মাইলো, কিছু কারণ থেকে আমার মাথায় ওভারস্প্লিফাইড মডেল ছিল correct
prosti থেকে
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.