سینتکس پیشرفته فیلترهای 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
- تعریف آرایه
$argsبا کلیدtax_query - درون
tax_query، آرایههای فرعی برای هر طبقهبندی ایجاد کنید. - کلید
relationرا رویANDقرار دهید تا همه شرایط برقرار شود. - بهروزرسانی
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
- در فایل functions.php یا یک افزونه، یک متغیر آرایهای تعریف کنید که شامل کلیدهای meta مورد نیاز باشد.
- هر شرط را به صورت آرایهای با کلیدهای
key،valueوcompareتعریف کنید. - در نهایت، کل آرایه را در پارامتر
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]);
|
|
| مقدارهای خاص | new WP_Query(['fields'=>'id=>parent', 'posts_per_page'=>5]);
|
نکتهٔ کارشناسی: اگر فقط نیاز به نمایش شماره صفحه دارید، استفاده از
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
- در فایل
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'); } } - در صورت نیاز، پارامترهای دیگر را نیز میتوانید تنظیم کنید، مانند
orderbyیاmeta_key. - اطمینان حاصل کنید که هوک فقط برای پرسوجوهای اصلی (
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
- در فایل
functions.php - درون تابع، پارامترهای
$queryرا بررسی کنید تا مطمئن شوید در حالت اصلی (is_main_query) هستید. - سپس
$query->set('tax_query', …)و$query->set('meta_query', …)را تنظیم کنید. - آخرین مرحله، افزودن هوک:
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
- یک تابع در
functions.phpایجاد کنید و هوکهایposts_joinوposts_where - در
posts_join، جدولwp_postmetaرا به جدولwp_postsمتصل کنید:LEFT JOIN {$wpdb->postmeta} ON {$wpdb->posts}.ID = {$wpdb->postmeta}.post_id AND {$wpdb->postmeta}.meta_key = 'price'. - در
posts_where، شرطmeta_value > 100را اضافه کنید. - سپس یک
WP_Queryساده باtax_queryبرای دستهبندی «محصولات» اجرا کنید.
این روش باعث میشود کوئری بهطور مستقیم
دیدگاه
دیدگاه ها غیر فعال است