روش های کوئری نویسی سفارشی(Custom Query) در وردپرس

هر نوع داده ای که به هر طریقی وارد وب سایت تان می کنید در دیتابیس وردپرس ذخیره می شود، وردپرس هم برای نمایش این اطلاعات بسته به اینکه در چه صفحه ای حضور دارید کوئری های مختلفی را اجرا می کند.

به عنوان مثال اگر در صفحه index.php باشید آخرین نوشته های(Latest Posts) وب سایت بر اساس مقدار posts_per_page (منوی تنظیمات/خواندن/گزینه بیشترین تعداد نوشته‌ها در هر برگهٔ وبلاگ) برگشت داده می شود.

اگر در صفحه یکی از دسته ها(Category) حضور داشته باشید آخرین پست های متعلق به آن دسته لیست می شود، اگر در صفحه single.php باشید فقط به اطلاعات آن پست خاص دسترسی خواهید داشت.

این مفهوم با عنوان سلسه مراتب قالب شناخته می شود که می توانید جزئیات کامل آن را در مطلب آموزشی آشنایی با مفهوم Template Hierarchy در وردپرس مطالعه فرمائید.

با این حال بعضی مواقع شرایطی پیش می آید که می خواهید این شیوه عملکردی و پیش فرض کوئری ها را تغییر دهید، به عنوان مثال در صفحه index.php نوشته های متعلق به یک طبقه خاص را Exclude کرده و نشان ندهید، یا در صفحه آرشیو(بایگانی) نوشته ها را به جای عنوان طبقه بر اساس تاریخ مرتب کنید.

خوشبختانه این قبیل کارها به راحتی در وردپرس قابل پیاده سازی است، ما در این مطلب آموزشی ۴ روش کوئری نویسی سفارشی را به شما آموزش می دهیم.

۱- اکشن pre_get_posts

اولین کاری که می توانید انجام دهید اجرای یک تابع اختصاصی از طریق اکشن pre_get_posts است، وردپرس این اکشن را قبل از فراخوانی(Fetch) اطلاعات از دیتابیس اجرا می کند.

برای این منظور یک تابع با نام دلخواه تعریف کرده و مشابه اسکریپت زیر به pre_get_posts الصاق کنید.

<?php
  function modiredev_custom_query( $query ) {
      // contents of function go here
   }
  add_action( 'pre_get_posts', 'modiredev_custom_query' );
?>

 

حالا تابع modiredev_custom_query از طریق پارامتر query$ به کوئری هایی که وردپرس اجرا می کند دسترسی دارد، اکشن pre_get_posts قبل از اجرای کوئری به شما اجازه می دهد تغییرات مدنظر خود را بر روی آن اعمال کنید.

بسیار مهم: در اکشن pre_get_posts به تمامی کوئری ها حتی مواردی که در پنل مدیریتی وردپرس اجرا می شوند دسترسی خواهید داشت، از این رو باید مطمئن شوید که کوئری هدف را به درستی انتخاب و تغییر می دهید.

برای این منظور باید از تگ های شرطی(Conditional Tags) استفاده کنید در غیر این صورت وردپرس تغییرات شما را همیشه اجرا خواهد کرد، برای درک بهتر موضوع به بررسی چند مثال می پردازیم.

۱- عدم نمایش یک طبقه خاص در صفحه index

در این مثال می خواهیم طبقه اسلایدر را از صفحه اصلی(Home Page) وب سایت خارج کنیم، برای این منظور کدهای زیر را در فایل functions.php قرار می دهیم.

function exclude_category_from_home_page( $query ) {
    if ( $query->is_home() && $query->is_main_query() ){
        $slider_cat_id = get_cat_ID( 'slider' );
        $query->set( 'category__not_in' => array( $slider_cat_id ) );
    }
    return $query;
}
add_action( 'pre_get_posts', 'exclude_category_from_home_page' );

 

چند نکته در رابطه با کدهای بالا:

  • همانطور که قبلا هم گفتیم وردپرس در هر صفحه کوئری متفاوت و البته مرتبط با آن صفحه را از روی URL درخواستی شناسایی و اجرا می کند، تابع is_main_query به ما این اطمینان خاطر را می دهد که تغییرات مدنظر بر روی کوئری شناسایی شده اعمال خواهد شد.
  • از تابع is_home برای تشخیص صفحه اصلی وب سایت استفاده کردیم.

روش های دیگر پیاده سازی این مثال در مطلب عدم نمایش پست های مرتبط با یک دسته خاص در وردپرس به طور کامل بررسی شده است.

۲- تغییر تعداد پست ها در صفحات آرشیو(بایگانی)

در دومین مثال مقدار posts_per_page را مستقیما در داخل کوئری تغییر می دهیم، کد زیر فقط در صفحات بایگانی اجرا خواهد شد و در هر صفحه به ۱۰ پست دسترسی داریم.

function get_one_post_home_page( $query ) {
    if ( $query->is_archive() && $query->is_main_query() ){
        $query->set( 'posts_per_page', 10 );
    }
    return $query;
}
add_action( 'pre_get_posts', 'get_one_post_home_page' );

 

۳- افزودن یک پست تایپ سفارشی(Custom Post Type) به صفحه index

وردپرس به طور پیش فرض در صفحه index.php فقط پست تایپ نوشته ها(Post) را لیست می کند، فرض کنید یک پست تایپ سفارشی به نام اخبار(news) ایجاد کرده اید و می خواهید اخبار را هم در کنار نوشته های وب سایت نمایش دهید، کد زیر اینکار را انجام می دهد.

function set_news_post_type() {
    if ( $query->is_home() && $query->is_main_query() ) {
       $query->set( 'post_type', array( 'post', 'news' ) );
    }
    return $query;
}
add_action( 'pre_get_posts', 'set_news_post_type');

 

اگر می خواهید پست تایپ سفارشی news به صفحه دسته ها اعمال گردد به جای تابع ()is_home از ()is_category استفاده کنید.

 ۴- اکشن pre_get_posts و پنل مدیریتی وردپرس

در نهایت برای تغییر کوئری های سطح مدیریتی مثال کاربردی و عملی نوشته های وردپرس: چگونه پست های کاربران را از دید یکدیگر مخفی کنیم؟ را بررسی نمائید.

۲- کلاس WP_Query

دومین روش پیاده سازی کوئری های سفارشی استفاده از کلاس WP_Query است، این کلاس قدرتمند در فایل query.php دایرکتوری wp-includes قرار دارد.

ساختار کوئری های WP_Query از اجزاء زیر تشکیل می شود:

  1. آرگومان هایی که برای کوئری ست می کنیم، مشابه query->set$ در اکشن pre_get_posts
  2. ایجاد یک آبجکت یا نمونه(Instance) از کلاس WP_Query
  3. حلقه(Loop)
  4. پاکسازی کوئری

پس از قرار دادن این اجزاء در کنار یکدیگر اسکریپت زیر تولید می شود.

<?php
  $args = array(
      // arguments for your custom query
  );

  // the query
  $query = new WP_Query( $args );

  // The Loop
  if ( $query->found_posts ) {

     while ( $query->have_posts() ) {

         $query->the_post();

	 // contents of the Loop

   }

 }

 // Restore original Post Data
 wp_reset_postdata();
?>

 

حالا در قالب یک مثال کاربردی می خواهیم عنوان ۵ خبر پربازدید را نمایش دهیم، در این مثال فرض کردیم تعداد بازدیدهای هر خبر در فیلد سفارشی views ذخیره شده است.

<?php 
   $args = array(
            'post_type' => 'news',
            'posts_per_page' => '5',
            'meta_key' => 'views',
            'orderby' => 'meta_value_num',
            'order' => 'DESC'
        );

   $query = new WP_Query( $args );
   if ( $query->found_posts ) {
	 while ( $query->have_posts()){
          $query->the_post();
         ?> 
          <p class="post-title"><?php echo get_the_title(); ?></p>
        <?php
     }
  }
  wp_reset_postdata();
?>

 

کلاس WP_Query متدها و پارامترهای متعددی دارد که بهتر است جزئیات کامل آن را در WP_Query Codex Page مطالعه کنید.

۳- تابع get_posts

اگر تا اینجای آموزش از روش های قبلی راضی نبودید پیشنهاد می کنیم ()get_posts را هم امتحان کنید، این تابع مستقیما به کلاس WP_Query دسترسی دارد و از آن استفاده می کند.

برای درک بهتر موضوع اینبار مثال قبلی را به کمک get_posts پیاده سازی می کنیم.

<?php 
$args = array(
            'post_type' => 'news',
            'posts_per_page' => '5',
            'meta_key' => 'views',
            'orderby' => 'meta_value_num',
            'order' => 'DESC'
        );

 $posts = get_posts( $args );

 if ( $posts ) {
	 foreach( $posts as $post ){
	   setup_postdata( $post );
        ?> 
          <p class="post-title"><?php echo get_the_title(); ?></p>
        <?php
    }
 }
 wp_reset_postdata();
?>

 

چند نکته در رابطه با کدهای بالا:

  • در تابع get_posts اگر پارامتر post_type ست نشود به طور پیش فرض از پست تایپ post استفاده خواهد شد، اما در کلاس WP_Query حتما باید post_type مشخص شود.
  • به جای حلقه while از foreach استفاده کردیم.
  •  این امکان وجود دارد که در حلقه foreach به جای فراخوانی توابعی مثل get_the_ID، the_content و … مستقیما از نام فیلدهای جدول wp_posts استفاده کنید.
  • مثلا post->ID ، $post->post_content$
  • در حلقه foreach برخی توابع مثل the_content در دسترس نیستند، از این جهت با فراخوانی setup_postdata می توانید به اینگونه توابع دسترسی داشته باشید.

۴- کلاس wpdb$

در نهایت آخرین و قدرتمندترین روش کوئری نویسی را بررسی می کنیم، اگر هیچکدام از روش های بالا نیازتان را برآورده نمی کند مطمئنا کلاس wpdb$ راه چاره خواهد بود. در این روش کوئری ها مستقیما بر روی دیتابیس اجرا می شوند، یک اشتباه کوچک می تواند زحمات شما را به باد دهد.

بسیار مهم: اگر کوئری شما آنقدر پیچیده است که کلاس WP_Query ،اکشن pre_get_posts و تابع get_posts پاسخگوی آن نیست آنگاه از کلاس wpdb$ استفاده کنید.

 

نکته: از کلاس wpdb$ می توانید برای نوشتن کوئری های بهینه استفاده کنید، کوئری هایی که نسبت به روش های قبلی سربار کمتری داشته باشند.

برای اطلاعات بیشتر پیشنهاد می کنیم مقاله دیتابیس وردپرس: مقدمه ای بر کلاس wpdb  را مطالعه فرمائید.

جمع بندی

آشنایی با روش های کوئری نویسی وردپرس و تسلط بر آنها مهارت ارزشمندی است که هر توسعه دهنده ای باید به آن مسلح شود، قابلیتی که به شما اجازه می دهد انواع و اقسام کوئری ها را بدون هیچگونه محدودیتی در پلاگین یا قالب خود پیاده سازی کنید.

نظرات و سوالات کاربران

پاسخی بگذارید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *