موزه ملي علوم و فناوري

جستجو در فیلدهای سفارشی وردپرس بدون افزونه

۲۴ فروردین ۱۳۹۶

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

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

کلیه اطلاعات مربوط به فیلدهای سفارشی در جدول postmeta دیتابیس ذخیره می شوند. این در حالی است که به صورت پیشفرض هنگام جستجو در وردپرس، نتایج از جدول posts گرفته می شوند. برای حل این مشکل لازم است که جدول postmeta را هنگام جستجو در نظر بگیریم. برای این کار از کد زیر استفاده می کنیم:

/**
 * Join posts and postmeta tables
 *
 * http://codex.wordpress.org/Plugin_API/Filter_Reference/posts_join
 */
function cf_search_join( $join ) {
    global $wpdb;

    if ( is_search() ) {    
        $join .=' LEFT JOIN '.$wpdb->postmeta. ' ON '. $wpdb->posts . '.ID = ' . $wpdb->postmeta . '.post_id ';
    }
    
    return $join;
}
add_filter('posts_join', 'cf_search_join' );

حال لازم است که کوئری مربوط به جستجو وردپرس را ویرایش کنیم:

/**
 * Modify the search query with posts_where
 *
 * http://codex.wordpress.org/Plugin_API/Filter_Reference/posts_where
 */
function cf_search_where( $where ) {
    global $pagenow, $wpdb;
   
    if ( is_search() ) {
        $where = preg_replace(
            "/(s*".$wpdb->posts.".post_titles+LIKEs*('[^']+')s*)/",
            "(".$wpdb->posts.".post_title LIKE $1) OR (".$wpdb->postmeta.".meta_value LIKE $1)", $where );
    }

    return $where;
}
add_filter( 'posts_where', 'cf_search_where' );

و در آخر هم لازم است با اضافه کردن دستور DISTINCT مانع نمایش نتایج تکراری شویم:

/**
 * Prevent duplicates
 *
 * http://codex.wordpress.org/Plugin_API/Filter_Reference/posts_distinct
 */
function cf_search_distinct( $where ) {
    global $wpdb;

    if ( is_search() ) {
        return "DISTINCT";
    }

    return $where;
}
add_filter( 'posts_distinct', 'cf_search_distinct' );

نتیجه گیری

کدهای بالا برای درک بهتر عملکرد هر قسمت توضیح داده شد. برای استفاده از کدها می توانید به راحتی کد تکمیل شده زیر را در فایل functions.php قالب اضافه کرده و آن را ذخیره کنید:

<?php
/**
 * Extend WordPress search to include custom fields
 *
 * http://8theme.ir
 */

/**
 * Join posts and postmeta tables
 *
 * http://codex.wordpress.org/Plugin_API/Filter_Reference/posts_join
 */
function cf_search_join( $join ) {
    global $wpdb;

    if ( is_search() ) {    
        $join .=' LEFT JOIN '.$wpdb->postmeta. ' ON '. $wpdb->posts . '.ID = ' . $wpdb->postmeta . '.post_id ';
    }
    
    return $join;
}
add_filter('posts_join', 'cf_search_join' );

/**
 * Modify the search query with posts_where
 *
 * http://codex.wordpress.org/Plugin_API/Filter_Reference/posts_where
 */
function cf_search_where( $where ) {
    global $pagenow, $wpdb;
   
    if ( is_search() ) {
        $where = preg_replace(
            "/(s*".$wpdb->posts.".post_titles+LIKEs*('[^']+')s*)/",
            "(".$wpdb->posts.".post_title LIKE $1) OR (".$wpdb->postmeta.".meta_value LIKE $1)", $where );
    }

    return $where;
}
add_filter( 'posts_where', 'cf_search_where' );

/**
 * Prevent duplicates
 *
 * http://codex.wordpress.org/Plugin_API/Filter_Reference/posts_distinct
 */
function cf_search_distinct( $where ) {
    global $wpdb;

    if ( is_search() ) {
        return "DISTINCT";
    }

    return $where;
}
add_filter( 'posts_distinct', 'cf_search_distinct' );
?>

کد بالا برای قسمت پیشخوان هم اعمال می شود. به این معنا که اگر در بخش پیشخوان هم جستجو انجام شود، این جستجو در بین فیلدهای سفارشی هم انجام خواهد شد.