برای انتخاب کلیدenter انتخاب کنید یا برای لغو ESC فشار دهید.

سینتکس پیشرفته فیلترهای WP_Query برای جستجوی هوشمند

فهم عمیق فیلترهای WP_Query و کاربردهای چندزبانه

فیلترهای WP_Query در وردپرس به عنوان ابزار اصلی برای جستجوی محتوا با شرایط پیچیده شناخته می‌شوند. در این بخش، به بررسی نحوه استفاده از meta_query و tax_query در ترکیب با پلتفرم‌های چندزبانه مانند WPML و Polylang می‌پردازیم. این ترکیب امکان جستجوی دقیق بر اساس زبان جاری و یا زبان‌های انتخابی را فراهم می‌کند.

یک مثال ساده: فرض کنید می‌خواهید مقالاتی را که در زبان فارسی هستند و دارای متادیتای خاصی (مثلاً featured = true) نمایش دهید. با اضافه کردن فیلتر lang به meta_query و استفاده از tax_query

برای بهبود کارایی در محیط‌های چندزبانه، توصیه می‌شود از کاشف‌های کش مثل WP Super Cache یا Redis Object Cache

ایجاد endpoint سفارشی در REST API با فیلترهای پیچیده

برای توسعه‌دهندگان، فراهم کردن یک endpoint سفارشی در REST API که از فیلترهای WP_Query بهره‌مند باشد، امکان ایجاد سرویس‌های پویا و پاسخگو را فراهم می‌کند. ابتدا، باید در فایل functions.php

add_action('rest_api_init', function () {
    register_rest_route('myplugin/v1', '/posts/', array(
        'methods'  => 'GET',
        'callback' => 'myplugin_get_posts',
    ));
});

function myplugin_get_posts($request) {
    $args = array(
        'post_type'   => 'post',
        'meta_query'  => array(
            array(
                'key'     => 'featured',
                'value'   => '1',
                'compare' => '=',
            ),
        ),
        'tax_query'   => array(
            array(
                'taxonomy' => 'category',
                'field'    => 'slug',
                'terms'    => array('news', 'updates'),
                'operator' => 'IN',
            ),
        ),
        'lang'        => $request->get_param('lang') ?: 'fa',
    );
    $query = new WP_Query($args);
    return $query->posts;
}

این کد یک endpoint جدید به نام /wp-json/myplugin/v1/posts/ ایجاد می‌کند که بر اساس پارامترهای lang، meta_query و tax_query

https://yourdomain.com/wp-json/myplugin/v1/posts/?lang=fa

در این مثال، پارامتر lang

دیباگینگ پیشرفته فیلترهای WP_Query با Query Monitor و لاگ‌گیری

برای رفع اشکال در کدهای پیچیده WP_Query، ابزارهای پیشرفته‌ای مانند Query Monitor و WP_DEBUG_LOG مفید هستند. در ابتدا، باید مطمئن شوید که WP_DEBUG و WP_DEBUG_LOG در فایل wp-config.php

define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);

سپس، با فعال‌سازی Query Monitor، می‌توانید تمام کوئری‌های اجرا شده، زمان پاسخ، و هشدارهای احتمالی را مشاهده کنید. برای مثال، در صورتی که meta_query شما به درستی عمل نکند، Query Monitor

استفاده از tax_query

در بسیاری از پروژه‌های وردپرس، نیاز است تا بر اساس چند دسته‌بندی و چند برچسب همزمان نتایج جستجو را محدود کنیم. tax_query

  1. تعریف آرایه $args با کلید tax_query
  2. درون tax_query، آرایه‌های فرعی برای هر طبقه‌بندی ایجاد کنید.
  3. کلید relation را روی AND قرار دهید تا همه شرایط برقرار شود.
  4. به‌روزرسانی WP_Query با آرایه جدید و اجرای get_posts().

مثال عملی

کد زیر یک نمونه کامل از ترکیب چند طبقه‌بندی را نشان می‌دهد:

$args = array(
'post_type' => 'post',
'tax_query' => array(
'relation' => 'AND',
array(
'taxonomy' => 'category',
'field' => 'slug',
'terms' => 'فرهنگ',
),
array(
'taxonomy' => 'post_tag',
'field' => 'slug',
'terms' => 'کتاب‌های-فارسی',
),
),
);
$posts = new WP_Query( $args );

این ساختار اجازه می‌دهد تا به راحتی فیلترهای پیچیده‌تری را با تغییر مقادیر relation به OR

نوع رابطه نمونه شرط نتیجه
AND دسته «فرهنگ» و برچسب «کتاب‌های فارسی» مقالات با هر دو شرط
OR دسته «فرهنگ» یا برچسب «کتاب‌های فارسی» مقالات با حداقل یکی از شرط‌ها

در پروژه‌های بزرگ، استفاده از tax_query ترکیبی می‌تواند باعث افزایش زمان پاسخگویی شود؛ حتماً از کش وردپرس برای کاهش بار دیتابیس بهره ببرید.

با درک کامل این ساختار، می‌توانید فیلترهای چندبُعدی را به‌صورت انعطاف‌پذیر و بهینه در برنامه‌های وردپرس خود پیاده کنید.

پیکربندی فیلترهای تاریخ با DateQuery

وقتی نیاز به جستجوی مقالات بر اساس بازه‌های زمانی خاص دارید، DateQuery در WP_Query امکاناتی را فراهم می‌کند که فراتر از پارامترهای ساده date_query

ساختار DateQuery پیشرفته

در زیر یک مثال ترکیبی از after، before و inclusive

$date_query = array(
array(
'after' => '2024-01-01',
'before' => '2024-12-31',
'inclusive' => true,
),
);

این آرایه را در args قرار دهید و در کنار سایر فیلترهای meta_query یا tax_query

ایجاد فیلتر سفارشی با pre_get_posts

برای اعمال فیلترهای سفارشی در تمام صفحات آرشیو یا در صفحات خاص، می‌توانید از هوک pre_get_posts بهره ببرید. این روش اجازه می‌دهد تا بدون تغییر در قالب، پارامترهای WP_Query

مثال:

function my_custom_date_filter( $query ) {
if ( $query->is_main_query() && !is_admin() && $query->is_archive() ) {
$query->set( 'date_query', array(
array(
'after' => '2023-01-01',
'inclusive' => true,
),
) );
}
}
add_action( 'pre_get_posts', 'my_custom_date_filter' );

این کد باعث می‌شود که تمام آرشیوهای اصلی فقط مقالاتی را نمایش دهند که پس از تاریخ ۱ ژانویه ۲۰۲۳ منتشر شده‌اند.

پارامتر نوع توضیح
after string تاریخ شروع بازه (YYYY-MM-DD)
before string تاریخ پایان بازه (YYYY-MM-DD)
inclusive

استفاده از meta_query برای فیلترهای ساختاریافته و فیلترهای منطقی

درباره meta_query در WP_Query، اکثر توسعه‌دهندگان تنها به‌صورت ساده‌ترین شکل آن را می‌دانند؛ یعنی فیلتر کردن بر اساس یک کلید و مقدار. اما با ترکیب relation و چندین شرط می‌توان فیلترهای پیچیده‌ای ایجاد کرد که به‌طور دقیق نیازهای پروژه را برآورده کنند. در ادامه، نحوه‌ی پیاده‌سازی یک پرس‌وجو چندگانه با meta_query را به‌صورت گام‌به‌گام بررسی می‌کنیم.

ساختار پایهٔ meta_query با رابطهٔ OR

  1. در فایل functions.php یا یک افزونه، یک متغیر آرایه‌ای تعریف کنید که شامل کلیدهای meta مورد نیاز باشد.
  2. هر شرط را به صورت آرایه‌ای با کلیدهای key، value و compare تعریف کنید.
  3. در نهایت، کل آرایه را در پارامتر meta_query و رابطهٔ relation را به OR تنظیم کنید.

نمونهٔ کد:

$query = new WP_Query(array(
    'post_type'   => 'product',
    'meta_query'  => array(
        'relation' => 'OR',
        array(
            'key'     => 'price',
            'value'   => 100,
            'compare' => '>='
        ),
        array(
            'key'     => 'rating',
            'value'   => 4.5,
            'compare' => '>='
        )
    )
));

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

مقایسهٔ روش‌های مختلف فیلتر با meta_query

روش زمان اجرا خوانایی کد
فیلترینگ ساده (یک شرط) کاهش سریع مناسب برای پروژه‌های کوچک
فیلترینگ ترکیبی (relation OR/AND) معتدل، بسته به تعداد شرط قابل‌دسترس برای توسعه‌دهندگان متوسط
فیلترینگ با custom SQL سرعت بالا در حجم داده زیاد نیاز به دانش SQL و نگهداری کد پیچیده

توجه: استفاده از meta_query در ترکیب با tax_query ممکن است باعث پیچیدگی در ساختار پرس‌وجو شود؛ در این موارد، بهتر است ابتدا فیلترهای tax را اعمال کنید و سپس بر اساس نتایج، meta_query را اعمال کنید.

در نهایت، برای بهینه‌سازی، همیشه فیلدهای مورد استفاده در meta_query

استفاده از post_status و post_type در فیلترهای ترکیبی برای جستجوی سفارشی

برخی مواقع، نیاز است تا در یک پرس‌وجو، چندین نوع محتوا و وضعیت انتشار را همزمان فیلتر کنیم. در این بخش، نحوه ترکیب پارامترهای post_type و post_status

ساختار پرس‌وجو با چند نوع محتوا

برای مثال، فرض کنید می‌خواهید مقالات و محصولات را با وضعیت publish و draft ترکیب کنید. در این حالت، می‌توانید از آرایه در پارامتر post_type و post_status

$query = new WP_Query(array(
    'post_type'   => array('post', 'product'),
    'post_status' => array('publish', 'draft'),
    'orderby'     => 'date',
    'order'       => 'DESC',
    'posts_per_page' => 10
));

این پرس‌وجو، ۱۰ رکورد اول را بر اساس تاریخ نزولی برمی‌گرداند که در آن‌ها، یا نوع محتوا مقاله باشد و وضعیت انتشار publish یا draft باشد، یا نوع محتوا محصول باشد و وضعیت انتشار publish یا draft باشد.

نکات عملی برای بهبود عملکرد

  • استفاده از fields => 'ids' برای دریافت فقط شناسه‌ها، حجم داده را کاهش می‌دهد.
  • اگر فقط می‌خواهید مقالات یا محصولات خاصی را فیلتر کنید، از meta_query برای محدود کردن بر اساس ویژگی‌های خاص استفاده کنید.
  • در صورت نیاز به فیلتر دقیق‌تر بر اساس تاریخ انتشار، پارامترهای date_query را به پرس‌وجو اضافه کنید.

برای نمونه، اگر می‌خواهید فقط مقالات منتشر شده در آخرین هفته را نمایش دهید، می‌توانید از کد زیر استفاده کنید:

$query = new WP_Query(array(
    'post_type'   => 'post',
    'post_status' => 'publish',
    'date_query'  => array(
        array(
            'after'     => '1 week ago',
            'inclusive' => true
        )
    ),
    'fields'      => 'ids'
));

این روش باعث می‌شود تا فقط مقالات منتشر شده در هفته گذشته را بارگیری کنید و بهینه‌سازی قابل توجهی در زمان پاسخ‌دهی به دست آ

بهینه‌سازی فیلترهای WP_Query با fields و posts_per_page برای بارگذاری سریع‌تر

در پروژه‌های بزرگ وردپرس، به‌دست آوردن فقط مقادیری که واقعاً نیاز دارید، می‌تواند مصرف منابع را به شدت کاهش دهد. پارامتر fields به شما اجازه می‌دهد تا نوع داده‌ای که می‌خواهید دریافت کنید را محدود کنید؛ مثلاً 'ids' برای دریافت فقط شناسه‌ها یا 'id=>parent' برای دریافت یک آرایه کلید‑مقدار post_id => parent_id. ترکیب این با posts_per_page و paged

مقایسه‌ی روش‌های بازگرداندن داده‌ها

روش کد نمونه نحوه‌ی مصرف منابع
کل‌اطلاعات new WP_Query(['post_status'=>'publish', 'posts_per_page'=>-1]);

بیشترین مصرف، تمام ستون‌ها و تمام نتایج
فقط شناسه‌ها new WP_Query(['fields'=>'ids', 'posts_per_page'=>10]);

کمترین مصرف، فقط ستون ID باز می‌گردد
مقدارهای خاص new WP_Query(['fields'=>'id=>parent', 'posts_per_page'=>5]);

بین‌المللی، فقط دو ستون ID و PARENT باز می‌گردد

نکتهٔ کارشناسی: اگر فقط نیاز به نمایش شماره صفحه دارید، استفاده از fields='ids' و سپس خواندن $query->posts می‌تواند به‌جای $query->have_posts() و حلقه‌ی کامل، زمان بارگذاری را تا ۷۰٪ کاهش دهد.

در ادامه، یک چک‌لیست عملی برای پیاده‌سازی این متدها آورده شده است:

  • تعیین posts_per_page
  • استفاده از paged برای ناوبری در صفحات بزرگ.
  • انتخاب fields متناسب با داده‌های مورد نیاز.
  • اطمینان از عدم استفاده از the_post() در حلقه‌ی زمانی که فقط شناسه‌ها را می‌خواهید.

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

کاهش خطاهای زمان اجرا با set_post_format و pre_user_query

کلاس WP_Query به‌صورت پیش‌فرض تمام مقالات را بر اساس فرمت پست (post format) فیلتر می‌کند. وقتی در یک قالب چند فرمت پست وجود دارد، اجرای پرس‌وجوهای پیچیده می‌تواند باعث ایجاد خطای Notice: Undefined index یا Fatal error شود. استفاده از هوک pre_user_query

نحوهٔ تنظیم پیش‌فرض‌های فیلتر با هوک pre_user_query

  1. در فایل functions.php یا افزونه‌ی خود، هوک را اضافه کنید:
    add_action('pre_user_query', 'set_default_post_format', 10, 2);
    function set_default_post_format($query, $user){
        if ($query->is_main_query() && !is_admin()){
            $query->set('post_format', 'post-format-standard');
        }
    }
  2. در صورت نیاز، پارامترهای دیگر را نیز می‌توانید تنظیم کنید، مانند orderby یا meta_key.
  3. اطمینان حاصل کنید که هوک فقط برای پرس‌وجوهای اصلی (is_main_query()) فعال می‌شود تا از تداخل با افزونه‌های دیگر جلوگیری شود.

به‌صورت خلاصه، ترکیب پارامترهای fields، posts_per_page و هوک‌های سفارشی، نه تنها سرعت و کارایی را بهبود می‌بخشد بلکه امکان کنترل دقیق‌تر بر روی خطاهای احتمالی را فراهم می‌آورد. در ادامه می‌توانید نمونه کد کامل را در این مخزن گیت‌هاب مشاهده کنید.

بهینه‌سازی واکنش‌های قالب با استفاده از pre_get_posts

یکی از راه‌های قدرتمند برای تغییر رفتار فیلترهای WP_Query در سطح کل سایت، فراخوانی هوشمند pre_get_posts است. این هوک به شما اجازه می‌دهد قبل از اجرای کوئری اصلی، پارامترهای آن را تغییر دهید، به‌طوری که تمام صفحات، آرکایو و حتی جستجوهای سفارشی تحت تأثیر یک تغییر واحد قرار گیرند. به‌عنوان مثال، می‌توانید تمام نمایش‌های آرکایو را محدود به مقالات با post_status فعال و post_type

چگونه می‌توانیم از pre_get_posts

در اینجا یک مثال گام‌به‌گام آورده شده است که در آن یک کوئری ترکیبی بر اساس tax_query و meta_query

  1. در فایل functions.php
  2. درون تابع، پارامترهای $query را بررسی کنید تا مطمئن شوید در حالت اصلی (is_main_query) هستید.
  3. سپس $query->set('tax_query', …) و $query->set('meta_query', …) را تنظیم کنید.
  4. آخرین مرحله، افزودن هوک: add_action('pre_get_posts', 'my_custom_pre_get_posts');

این روش باعث می‌شود تمام کوئری‌های اصلی سایت، بدون نیاز به تغییر در کدهای قالب، به صورت خودکار فیلتر شوند. برای مشاهده نمونه‌های بیشتر، به مقاله پیشرفته WP_Query مراجعه کنید.

نکته: اگر در هوک pre_get_posts از is_admin() استفاده کنید، مطمئن شوید که تغییرات فقط در بخش وب‌سایت اعمال می‌شود؛ در غیر این صورت، کوئری‌های مدیریت مخرب خواهد شد.

روش سرعت اجرا پوشش
استفاده از pre_get_posts

خیلی سریع (یک بار در چرخه‌ی درخواست) تمام کوئری‌های اصلی
استفاده از posts_where و posts_join

متوسط (در هر کوئری) تنها کوئری‌های سفارشی
استفاده از هوک query_vars

سست (در هر درخواست) کوئری‌های کم‌استفاده

توجه داشته باشید که pre_get_posts به‌صورت پیش‌فرض در محیط وردپرس فعال است و نیازی به افزودن افزونه خاصی نیست؛ اما برای دسترسی به مستندات رسمی، می‌توانید به سایت توسعه‌دهندگان وردپرس مراجعه کنید.

یکپارچه‌سازی فیلترهای WP_Query با فیلدهای ACF و ایجاد کوئری‌های JOIN

افزونه Advanced Custom Fields (ACF) امکان ذخیره‌سازی داده‌های ساختاریافته در فیلدهای سفارشی را فراهم می‌کند. برای دسترسی به این داده‌ها در کوئری‌های WP_Query، معمولاً از meta_query استفاده می‌شود، اما در برخی موارد، به‌خصوص زمانی که فیلدهای متنوعی در چند جدول ذخیره می‌شوند، نیاز به اجرای JOIN مستقیم با جدول wp_postmeta

چگونه یک کوئری JOIN برای فیلدهای ACF بسازیم؟

در این مثال، فرض کنید می‌خواهید تمام مقالاتی را پیدا کنید که در فیلد ACF «price» مقدار بالاتر از ۱۰۰ داشته باشند و در عین حال در دسته‌بندی «محصولات» باشند. به جای استفاده از meta_query، می‌توانید از WP_Query همراه با posts_join و posts_where

  1. یک تابع در functions.php ایجاد کنید و هوک‌های posts_join و posts_where
  2. در posts_join، جدول wp_postmeta را به جدول wp_posts متصل کنید: LEFT JOIN {$wpdb->postmeta} ON {$wpdb->posts}.ID = {$wpdb->postmeta}.post_id AND {$wpdb->postmeta}.meta_key = 'price'.
  3. در posts_where، شرط meta_value > 100 را اضافه کنید.
  4. سپس یک WP_Query ساده با tax_query برای دسته‌بندی «محصولات» اجرا کنید.

این روش باعث می‌شود کوئری به‌طور مستقیم