как создать правильный запрос для получения списка пользователей с мета-ключом, связанным с таксономией


Я хочу перечислить пользователей на основе подкатегории (которая является таксономией). В нем отображаются пользователи из всех подкатегорий, а не из той, которую я выбираю в подкатегории с серверной части. Код приведен ниже, пожалуйста, сообщите, что я делаю неправильно:

Options.php

<?php

if (!defined('FW'))
    die('Forbidden');



$options = array(
    'heading' => array(
        'label' => esc_html__('Heading', 'listingo'),
        'desc' => esc_html__('Add heading. Leave it empty to hide', 'listingo'),
        'type' => 'text',
    ),
    'sub_heading' => array(
        'label' => esc_html__('Sub Heading', 'listingo'),
        'desc' => esc_html__('Add sub heading. Leave it empty to hide', 'listingo'),
        'type' => 'text',
    ),
    'view' => array(
        'type' => 'select',
        'value' => 'list',
        'desc' => esc_html__('Select listing View', 'listingo'),
        'label' => esc_html__('Listing View', 'listingo'),
        'choices' => array(
            'list' => esc_html__('List', 'listingo'),
            'grid' => esc_html__('Grid', 'listingo'),
        ),
    ), 
    'sub_category' => array(
        'type' => 'multi-select',
        'label'     => esc_html__('Select Sub Categories', 'listingo'),
        'population' => 'taxonomy',
        'source' => 'sub_category',
        'limit' => 500,
        'desc' => esc_html__('Show users by sub category selection. Leave it empty to show from all categories', 'listingo'),
    ),
    'show_posts' => array(
        'type' => 'slider',
        'value' => 8,
        'properties' => array(
            'min' => 1,
            'max' => 100,
            'sep' => 1,
        ),
        'label' => esc_html__('Show No of Posts', 'listingo'),
    ),
    'show_pagination' => array(
        'type' => 'select',
        'value' => 'no',
        'label' => esc_html__('Show Pagination', 'listingo'),
        'desc' => esc_html__('', 'listingo'),
        'choices' => array(
            'yes' => esc_html__('Yes', 'listingo'),
            'no' => esc_html__('No', 'listingo'),
        ),
        'no-validate' => false,
    ),
);

View.php

<?php
if (!defined('FW'))
    die('Forbidden');

global $paged;

$per_page = intval(8);
if (!empty($atts['show_posts'])) {
    $per_page = $atts['show_posts'];
}

$pg_page = get_query_var('page') ? get_query_var('page') : 1; //rewrite the global var
$pg_paged = get_query_var('paged') ? get_query_var('paged') : 1; //rewrite the global var
$cat_sepration  = !empty( $atts['sub_category'] ) ? $atts['sub_category'] : '';


//paged works on single pages, page - works on homepage
$paged = max($pg_page, $pg_paged);
$limit  = (int) $per_page;

$meta_query_args = array();
$query_args = array(
    'role__in' => array('professional', 'business'),
    'post_type' => 'sp-provider',
    'orderby' => 'meta_value_num',
    'order' => 'DESC',
);

//Verify user
$meta_query_args[] = array(
    'key' => 'verify_user',
    'value' => 'on',
    'compare' => '='
);
//active users filter
$meta_query_args[] = array(
    'key' => 'activation_status',
    'value' => 'active',
    'compare' => '='
);



if (!empty($meta_query_args)) {
    $query_relation = array('relation' => 'AND',);
    $meta_query_args = array_merge($query_relation, $meta_query_args);
    $query_args['meta_query'] = $meta_query_args;
}

if( !empty( $cat_sepration ) ) {
    foreach( $cat_sepration as $key => $value ){
        $meta_category[] = get_terms( array(
                        'taxonomy'      => 'sub_category',
                        'include'       => $value,
                        'hide_empty'    => 0

        ));
    }

}

//By Sub Categories
if( !empty( $meta_category ) ) {
    $query_relations = array( 'relation' => 'OR',);
    $meta_query_args    = array_merge( $query_relations, $meta_category );
    $query_args['meta_query'][] = $meta_query_args;
}

if( !empty( $atts['show_pagination'] ) && $atts['show_pagination'] === 'yes'){
    $offset = ($paged - 1) * $limit;
} else{
    $offset = 0;
}

$query_args['number'] = $limit;
$query_args['offset'] = $offset;

$user_query = new WP_User_Query($query_args);
$total_users = $user_query->total_users;
?>
<div class="sc-listing-bycat-grid sp-featured-providers-v2 tg-haslayout spv4-listing">
    <?php if (!empty($atts['heading']) || !empty($atts['sub_heading'])) { ?>
        <div class="col-xs-12 col-sm-12 col-md-10 col-md-push-1 col-lg-8 col-lg-push-2">
            <div class="tg-sectionheadvtwo">
                <div class="tg-sectiontitle">
                    <?php if (!empty($atts['heading'])) { ?><span><?php echo esc_attr($atts['heading']); ?></span><?php } ?>
                    <?php if (!empty($atts['sub_heading'])) { ?><h2><?php echo esc_attr($atts['sub_heading']); ?></h2><?php } ?>
                </div>
            </div>
        </div>
    <?php } ?>
    <div class="tg-featuredproviders tg-listview">
        <div class="tg-featuredproviders">
            <div class="row">
                <?php
                if (!empty($user_query->results)) {
                    foreach ($user_query->results as $user) {
                        $username = listingo_get_username($user->ID);
                        $category = get_user_meta($user->ID, 'sub_category', true);
                        $avatar = apply_filters(
                                'listingo_get_media_filter', listingo_get_user_avatar(array('width' => 92, 'height' => 92), $user->ID), array('width' => 92, 'height' => 92)
                        );
                        ?>
                        <div class="col-xs-12 col-sm-6 col-md-3 col-lg-3 tg-verticaltop">
                            <div class="tg-featuredad">
                                <?php do_action('listingo_result_avatar_v2', $user->ID,'',array('width' => 275, 'height' => 152)); ?>
                                <div class="tg-featuredetails">
                                    <?php do_action('listingo_result_tags_v2', $user->ID); ?>
                                    <div class="tg-title">
                                        <h2><a href="<?php echo esc_url(get_author_posts_url($user->ID)); ?>"><?php echo esc_attr($username); ?></a></h2>
                                    </div>
                                    <?php do_action('sp_get_rating_and_votes', $user->ID); ?>
                                </div>
                                <ul class="tg-phonelike">
                                    <?php do_action('listingo_get_user_meta','phone',$user);?>
                                    <?php do_action('listingo_add_to_wishlist', $user->ID); ?>
                                </ul>
                            </div>
                        </div>
                        <?php
                    }
                }
                ?>
            </div>
        </div>
    </div>
    <?php if (!empty($total_users) && !empty($limit) && $total_users > $limit && isset($atts['show_pagination']) && $atts['show_pagination'] == 'yes') { ?>
        <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
            <?php listingo_prepare_pagination($total_users, $limit); ?>
        </div>
    <?php } ?>
</div>
Author: simongcc, 2020-04-09

1 answers

Цель

Я хочу перечислить sp_provider (больницы, клиники, врачи), чей sub_category предположим 'neurology'

Перефразируя слова:

Я хочу перечислить пользователей с категорией провайдера sp (мета-значение), такой как "больница", и у пользователя есть подкатегория (мета-значение) "неврология"

  • sp_provider - это мета-значение в профиле пользователя (sp-провайдер, возможно, тип сообщения или что-то еще для редактирования экрана управления пользователями)
  • суб категория также является мета-значением, хранящимся в профиле пользователя, считается, что список связан с типом записи sub_categories с таксономией sub_category

Перечислите всех пользователей с выбранными sp provider, sub category и учетная запись пользователя verified и activated

Шаги по созданию правильного запроса

  • преобразуйте идентификатор выбранных терминов в slug
  • создайте запрос на основе терминов slug

Примечания к вашим метаданным и предостережения Ваши данные подкатегории сериализованный. Я полагал, что это массив, и для удобства обработки весь массив сериализуется перед сохранением. Это затрудняет такие операции, как поиск. Чтобы точно справиться с этим, сначала нужно его отменить. В некоторых случаях, таких как ваш, если он предназначен только для чтения без какой-либо операции сохранения, это было бы нормально, и ваши данные представляют собой простой массив значений.

Говоря о данных, это все еще безопасно, хотя это не лучший выбор. Если это связано с обновлением данных, то это было бы очень опасно, потому что сериализованные данные очень легко взломать. Это приведет ваши данные, по крайней мере, это поле полностью в бесполезное состояние, или, если обработки ошибок недостаточно, это нарушит ваш php, в некоторых худших случаях даже будет отображаться пустая страница, что не редкость, когда шаблон полагается на данные для вывода шаблона. Вы можете принять это во внимание.

Примечания к ключевому слову запроса "В"

// IN не работает, если сохраненные данные представляют собой сериализованный массив, первоначально В работе с массивом() при сравнении списка данных с предоставленным массивом.

// $meta_query_args[] = array(
//     'key' => 'sub_category',
//     'value' => array( 'cardiology', 'neurology', 'oncology' ),
//     'compare' => 'IN'
// );

Следующий список пользователей на основе категорий и подкатегорий при условии, что пользователь проверен и активирован

// suppose you get a value somewhere
$cat_sepration = array(
    "48", "50"
);

$query_args = array(
    // 'post_type' => 'sp-provider', // ignored by user query, it is for post query
    'role__in' => array('professional', 'business'),
    'orderby' => 'meta_value_num',
    'order' => 'DESC',
);

// prepare term slug from term id for searching
// because the $cat_separation is a list of ID, you need to convert to slugs before putting into user query to search
$terms = get_terms( array(
    'taxonomy' => 'sub_category',
    'include' => $cat_sepration, // it takes the selected id here and convert to slugs
    'fields' => 'slugs',
    'hide-empty' => false,
) );

// check point
var_dump( $terms ); // a list of terms slug for use to search for user in related category 

$meta_query_args = array();

// Verify user
$meta_query_args[] = array(
    'key' => 'verify_user',
    'value' => 'on',
    'compare' => '='
);

// active users filter
$meta_query_args[] = array(
    'key' => 'activation_status',
    'value' => 'active',
    'compare' => '='
);

// sp category
// since your data is single value, IN will also work
$meta_query_args[] = array(
    'key' => 'spcategory_search',
    'value' => array( 'Hospital', 'Clinic' ), // case sensitive, array is for multiple
    'compare' => 'IN' // = is for one value, IN is for multiple
);

// ** this is how to the `category query` is properly created
// sub category
// the following can search the serialized data in database
// this comparing method using LIKE operator is similar to those used in role__in comparison in WordPress Core
$category_query_args = [];
foreach ($terms as $key => $term) {
    $category_query_args[] = array(
        'key' => 'sub_category',

// without :" is also work, :" increase the accuracy because it relies on the LIKE operator comparing to the serialized data. A text inside serialized data is beginning with :"something" so it helps to match

        'value' => ':"' . $term, 
        'compare' => 'LIKE',
    );
}

$meta_query_args[] = array(
    array(
        // to ensure the user have all the categories at the same time, so the operator is AND
        'relation' => 'AND',
        $category_query_args,

        // the following is proved to work in test data, it is written as a foreach above for programatic reason

        // here is an expanded version of $category_query_args (the above for-each loop for reference)
        // because 'LIKE' is used, it searches based on similar keywords
        // array(
        //  'key' => 'sub_category',
        //  'value' => 'cardiology', // or ':"cardiology', means beginning with :"cardiology
        //  'compare' => 'LIKE',
        // ),
        // array(
        //  'key' => 'sub_category',
        //  'value' => 'neurology',
        //  'compare' => 'LIKE',
        // ),
        // array(
        //  'key' => 'sub_category',
        //  'value' => 'Oncology',
        //  'compare' => 'LIKE',
        // )
    ),
);

if (!empty($meta_query_args)) {
    $query_relation = array('relation' => 'AND',);
    $meta_query_args = array_merge($query_relation, $meta_query_args);
    $query_args['meta_query'] = $meta_query_args;
}
$user_query = new WP_User_Query($query_args);

// for debugging purpose
// var_dump($query_args);

// check point
var_dump($user_query->request); // you may confirm the SQL query and run in sql platform/tools

$users = $user_query->get_results(); // if result is result, you may do any operation hereafter

// check point
foreach ($users as $key => $user) {
    print_r(get_user_meta($user->ID)); // confirm the meta value
}

// each of the above step proved to be working with simulated data
 1
Author: simongcc, 2020-04-17 09:35:45