Массивы Мета-запросов 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.
Спасибо!
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).")
У вас возникнут проблемы с вашим текущим подходом, потому что, как вы заметили, идентификаторы сохраняются в виде сериализованных массивов в одном поле. Более простым подходом было бы сохранить каждый лайк в виде одной записи 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
Поэтому просто замените часть запроса на свой массив идентификаторов пользователей.
У меня была похожая проблема, и я решил ее с помощью сериализации(), вы можете использовать ir в случае, если vale, с которым вы работаете, является целым числом, вот мой пример:
$args = array(
'meta_query' => array(
array(
'key' => 'my_meta_key',
'value' => serialize(strval($my_id)),
'compare' => 'LIKE'
)
)
);
$posts = get_posts( $args );
И это все, вы подготовили свой мета-запрос.
Ваш запрос верен. Но поскольку вы храните идентификаторы пользователей в виде строки, ваш запрос не будет работать. Сохраните идентификатор пользователя в одном мета-значении для публикации.
add_post_meta($post->ID, 'like', $user_id, false);
И заменить 'compare' => 'IN'
на 'compare' => 'LIKE'