Массивы Мета-запросов WordPress


Я создаю способ, с помощью которого мои пользователи будут "лайкать" публикацию.

У меня будет множество пользователей, которым понравились сообщения:

$user_ids = array(60, 61, 62, 63);

И тогда у публикации будет post_meta, которая сохраняет идентификатор пользователя при нажатии кнопки "нравится" на публикации, например:

// Build array of user IDs that have liked this post
$likes = array(61, 62);

// Save array
update_post_meta($post->ID, likes, $likes);

Итак, как я могу вернуть все сообщения, которые понравились пользователям. Вот как я это делаю в настоящее время, что не работает.

$args = array(
    'post_type'         => 'post',
    'post_status'       => 'publish',
    'posts_per_page'    => -1,
    'orderby'           => 'rand',
    'meta_query'        => array(
        'relation'  => 'AND',
        array(
            'key'       => 'likes',
            'value'     => $user_ids,
            'compare'   => 'IN'
        )
    )
);
$posts = get_posts($args);

Это должно вернуть все записи, у которых есть "60, 61, 62, 63", сохраненные в мете "нравится". Но это возвращает 0 результатов.

Теперь я думаю, что это потому, что WordPress сериализует массивы, когда они сохраняются в post_meta.

Итак, как мне выполнить такой запрос? Возможно ли это вообще? Возможно, мне придется использовать класс $wpdb.

Спасибо!

Author: M Khalid Junaid, 2013-08-03

4 answers

Попробуйте это с WP_Query нет необходимости в отношении, просто используйте часть сравнения с IN

 $user_ids = array(60, 61, 62, 63);
 $args = array(
   'post_type' => 'post',
   'meta_key' => 'likes',
   'post_status'       => 'publish',
   'posts_per_page'    => -1,
   'orderby'           => 'rand',       
   'order' => 'ASC',
   'meta_query' => array(
       array(
           'key' => 'likes',
           'value' => $user_ids, //array
           'compare' => 'IN',
       )
   )
 );
 $query = new WP_Query($args);

См. Приведенный выше пример заголовка "Параметры времени" WP_ запрос

ИЛИ с помощью get_posts попробуйте это

$args = array(
    'post_type'         => 'post',
    'post_status'       => 'publish',
    'posts_per_page'    => -1,
    'orderby'           => 'rand',
    'meta_query'        => array(

        array(
            'key'       => 'likes',
            'value'     => $user_ids,
            'compare'   => 'IN'
        )
    )
);
$posts = get_posts($args);

ИЛИ с помощью пользовательского запроса вы можете сделать следующее

global $wpdb;

$liked_posts=$wpdb->get_results("SELECT * FROM `wp_posts` WHERE 
post_type='post' AND post_status ='publish' AND ID
 IN(
SELECT post_id FROM `wp_postmeta` WHERE meta_key='likes' 
AND meta_value IN (".join(',',$user_ids).")
) ORDER BY RAND()");

Также не храните массив идентификаторов в одной строке, вместо этого пройдите по массиву идентификаторов и нормализуйте ваши данные "нравится" вручную, не сериализуйте данные в поле базы данных. Вот что Нормализация базы данных предназначен для и вставляет каждый идентификатор в новую строку, потому что

Wordpress хранит мета-значения в виде строк. Когда вы проходите update_post_meta массив, он автоматически преобразует его в строку. Что вам нужно будет сделать, это unserialize, когда вы пытаетесь прочитать данные, но в mysql вы не можете unserialize данные столбца в запросе, потому что mysql не знает о сериализации php

$likes = array(61, 62);

foerach($likes as $l){

update_post_meta($post->ID, "likes", $l);

}

И ниже приведен запрос вы просили в комментариях о вознаграждении

Если дан ответ $wpdb, пожалуйста, поясните, как учитывать категорию (включать и исключать) и игнорировать сообщения по массиву идентификаторов

$liked_posts=$wpdb->get_results("
SELECT * FROM `wp_posts` wp
INNER JOIN `wp_term_relationships` wtr ON (wp.`ID`=wtr.`object_id`)
INNER JOIN  `wp_term_taxonomy` wtt ON (wtr.`term_taxonomy_id` =wtt.`term_taxonomy_id`)
WHERE  wp.post_type='post' AND wp.post_status ='publish' AND wp.ID
 IN(
SELECT post_id FROM `wp_postmeta` WHERE meta_key='likes' 
AND meta_value IN (".join(',',$user_ids).")
)  AND wp.ID NOT IN (100,101,102)
AND wtt.`term_id` IN(1,2,3) AND wtt.`term_id` NOT IN (4,5,6,)    
ORDER BY RAND() ");

Я использовал INNER JOINs в wp_term_relationships и wp_term_taxonomy в таблице wp_term_relationships хранится соотношение должностей и таксономия категории, а в таблице wp_term_taxonomy есть таксономия категории, а также идентификатор категории

Вот часть, которая охватывает

1. категория (включать и исключать)

AND wtt.`term_id` IN(1,2,3) AND wtt.`term_id` NOT IN (4,5,6,) 

2. игнорировать сообщения по массиву идентификаторов

AND wp.ID NOT IN (100,101,102) 
or $postids =array(100,101,102);
AND wp.ID NOT IN (".join(',',$postids).")
 19
Author: M Khalid Junaid, 2013-08-07 20:39:11

У вас возникнут проблемы с вашим текущим подходом, потому что, как вы заметили, идентификаторы сохраняются в виде сериализованных массивов в одном поле. Более простым подходом было бы сохранить каждый лайк в виде одной записи postmeta. Так что meta_key = "нравится" и meta_value = идентификатор пользователя.

Поэтому для сохранения лайков переключитесь с update_post_meta на add_post_meta:

/** The fourth parameter, false, tells WP that there can be multiple
  * post_meta entries with the same meta_key. It's false by default, just here
  * here for reference
  */
add_post_meta($post->ID, 'like', $user_id, false);

Затем, чтобы посты понравились определенному пользователю, вам просто нужно сделать:

$liked_posts = $wpdb->get_results("SELECT post_id FROM {$wpdb->prefix}postmeta 
              WHERE meta_key = 'like' AND meta_value = $user_id");

Чтобы получить результаты для ряда пользователей на один раз, например, идентификатор пользователя 4, 23, 39 и т.д.

$liked_posts_by_user = $wpdb->get_results("SELECT meta_value as user_id, 
         GROUP_CONCAT(post_id) as posts FROM {$wpdb->prefix}wp_postmeta 
         WHERE meta_value IN('22','23','24') GROUP BY user_id

Это даст вам такие результаты, как:

  user_id    posts
   23         1
   25         2,40,3

Поэтому просто замените часть запроса на свой массив идентификаторов пользователей.

 2
Author: wunderdojo, 2013-08-06 19:56:36

У меня была похожая проблема, и я решил ее с помощью сериализации(), вы можете использовать ir в случае, если vale, с которым вы работаете, является целым числом, вот мой пример:

    $args = array(
    'meta_query' => array(
        array(
            'key' => 'my_meta_key',
            'value' => serialize(strval($my_id)),
            'compare' => 'LIKE'
        )
    )
);
$posts = get_posts( $args );

И это все, вы подготовили свой мета-запрос.

 1
Author: yunieski dieguez garcia, 2015-07-15 13:48:24

Ваш запрос верен. Но поскольку вы храните идентификаторы пользователей в виде строки, ваш запрос не будет работать. Сохраните идентификатор пользователя в одном мета-значении для публикации.

add_post_meta($post->ID, 'like', $user_id, false);

И заменить 'compare' => 'IN' на 'compare' => 'LIKE'

 0
Author: Mangesh Parte, 2013-08-07 12:08:40