Як зробити запит на повідомлення за допомогою часткового мета ключа?


9

У мене є функція, яка зберігає статус "подобається" для публікації як мета мета. Я хочу пов’язати це "подобається" з користувачем, який йому сподобався, тому я встановив користувацьке поле під назвою "like_status_ {user_id}" (де {user_id} - ідентифікатор користувача, який зараз увійшов), який я зберігаю як 0 або 1. Отже, для публікації з кількома "лайками" в db буде встановлено кілька мета-значень, які встановлюються так:

'meta_key' = 'like_status_0'
'meta_value' = 1
'meta_key' = 'like_status_2'
'meta_value' = 1
'meta_key' = 'like_status_34'
'meta_value' = 1

....і так далі.

У певній публікації потенційно є тисячі лайків. Як би я запустив запит, який показав, чи хтось ще любив цю публікацію?

Я думав щось подібне:

$query = new WP_Query(array(
    'meta_key' => 'like_status_{user_id}',
    'meta_value' => 1,
));

Я намагаюся надіслати сповіщення всім, хто сподобався дописом, коли комусь ще подобається цей пост ... щось на кшталт: "Ей, хтось ще любив цю публікацію, яка вам сподобалась. Ви повинні перевірити це!" Але мені потрібен спосіб дізнатися, чи сподобався комусь ще цей пост, і якщо так, то ким би вони були, щоб я міг їх повідомити.

Якщо це неможливо, ви могли б запропонувати кращий спосіб зберігання цих даних як post_meta, зберігаючи ефективність швидкого оновлення статусу одного користувача на посаді?

Відповіді:


6

На жаль , ви не можете виконати , meta_queryвикористовуючи LIKEпорівняння по meta_keyвартості при використанні WP_Query. Я був по цій дорозі ...

Натомість у вас є пара інших варіантів, якщо ви хочете підтримувати подібні відносини статусу як постмета, а не користувацькі мета та або мета у користувацькій таблиці.

Варіант 1

  • не потребує змін вашої мета-схеми
  • використовує wpdbклас для виконання спеціального запиту

Приклад:

//when a user likes a post...
$current_user_id = get_current_user_id();
add_post_meta($current_user_id, "like_status_{$current_user_id}", 1, false);

//later in the request...
global $wpdb;

$results = $wpdb->get_results(
    "
    SELECT meta_key 
    FROM {$wpdb->prefix}postmeta 
    WHERE meta_key 
    LIKE 'like_status_%'
    ",
    ARRAY_N
);

$results = array_map(function($value){

    return (int) str_replace('like_status_', '', $value[0]);

}, $results);

array_walk($results, function($notify_user_id, $key){

    //apply to all users except the user who just liked the post
    if ( $notify_user_id !== $current_user_id ) {
        //notify logic here...           
    }

});

Примітка: логіка може бути додатково спрощена, якщо ви хочете.

Варіант 2

  • вимагає змінити вашу мета-схему
  • вимагає збереження ідентифікатора користувача як мета-значення
  • дозволяє використовувати WP_Queryразом зmeta_query

Варіант 2 вимагає, щоб ви змінили свій мета-ключ like_status_{user_id}на щось універсальне, наприклад, like_statusабо liked_by_user_idде, в свою чергу, замість того, щоб зберігати значення 1проти ключа, замість цього ви зберігаєте ідентифікатор користувача як значення.

//when a user likes a post...
$current_user_id = get_current_user_id();
add_post_meta($current_user_id, "liked_by_user_id", $current_user_id, false);

//later in the request
$args = array(
    'post_type'  => 'post', //or a post type of your choosing
    'posts_per_page' => -1,
    'meta_query' => array(
        array(
            'key' => 'liked_by_user_id',
            'value' => 0,
            'type' => 'numeric'
            'compare' => '>'
        )
    )
);

$query = new WP_Query($args);   

array_walk($query->posts, function($post, $key){

    $user_ids = get_post_meta($post->ID, 'liked_by_user_id');

    array_walk($user_ids, function($notify_user_id, $key){

        //notify all users except the user who just like the post
        if ( $notify_user_id !== $current_user_id ) {

            //notify logic here...
            //get user e.g. $user = get_user_by('id', $notify_user_id);

        }

    });

});

1
Зараз з 5.1 перегляньте мою відповідь нижче
К. Тромп

@ K.Tromp Huzzah!
Адам

Будь ласка, оновіть прийняту відповідь, щоб відображати останні можливості WP або @ K.Tromp відповідь позначена як найсвіжіша відповідь
zumek

10

Конкретно відповісти на ваше запитання досить складно. Перша частина, проте, легка. Нещодавно я робив щось подібне на stackoverflow

Мета-ключі порівнюються і відповідають точно. WP_Queryне мають можливості коригувати цю поведінку простим параметром, але ми завжди можемо представити його, а потім відрегулювати posts_whereпункт для LIKEпорівняння мета-клавіш.

ФІЛЬТР

Це просто базовий фільтр, відрегулюйте його за потребою.

add_filter( 'posts_where', function ( $where, \WP_Query $q )
{ 
    // Check for our custom query var
    if ( true !== $q->get( 'wildcard_on_key' ) )
        return $where;

    // Lets filter the clause
    $where = str_replace( 'meta_key =', 'meta_key LIKE', $where );

    return $where;
}, 10, 2 );

Як бачимо, фільтр запускається лише тоді, коли ми встановимо новий спеціальний параметр, wildcard_on_keyна true. Коли це перевіряється, ми просто змінюємо =компаратор на LIKEкомпаратор

Лише зауваження щодо цього, LIKEпорівняння за своєю суттю дорожче, ніж інші порівняння

ПИТАННЯ

Ви можете просто запитувати свої публікації як слід, щоб отримати всі повідомлення з мета-ключами like_status_{user_id}

$args = [
    'wildcard_on_key' => true,
    'meta_query'      => [
        [
            'key'   => 'like_status_',
            'value' => 1,
        ]
    ]
];
$query = new WP_Query( $args );

ІНШІ ПИТАННЯ

Спеціальні поля не впливають на продуктивність, ви можете прочитати мою публікацію з цього приводу тут . Мене все ж хвилює те, що ви говорите, що кожен пост може мати сотні чи тисячі лайків. Це може вплинути на отримання продуктивності та кешування такої великої кількості спеціальних польових даних. Він також може засмітити ваш db величезною кількістю непотрібних спеціальних даних про поле, що робить його досить важким у підтримці.

Я не є великим прихильником зберігання серіалізованих даних у користувацьких полях, оскільки не можна шукати чи замовляти серіалізовані дані. Однак я б радив зберігати всі ідентифікатори користувача у масиві під одним спеціальним полем. Ви можете просто оновити масив з ідентифікатором користувача, коли користувачеві подобається публікація. Отримати користувальницькі дані про поле та прокрутити їх через масив ідентифікаторів та зробити щось із ідентифікаторами дуже просто. Просто погляньтеget_post_meta()

Оновлення спеціального поля також легко. Для цього вам потрібно буде вивчити update_post_meta(), я не знаю, як ви створюєте свої власні поля, але update_post_meta()це, безумовно, щось, що ви хотіли б використати.

Якщо вам потрібно надсилати електронні листи чи надсилати сповіщення, коли користувацьке поле оновлюється, у вас є такі гачки, з якими можна працювати. ( Див. update_metadata()Контекст )

ВИСНОВОК

Перед тим, як я опублікую це, ще раз, перш ніж відправлятися по серіалізованому маршруту, переконайтеся, що вам не потрібно буде сортувати за відсортованими даними або шукати конкретні дані всередині серіалізованих даних.


1
Дякую за пояснення щодо продуктивності post_meta! Супер корисно.
codecribblr

Це має бути прийнятою відповіддю, завжди краще використовувати фільтри, а не користувацькі запити. Також зауважте, якщо ви використовуєте get_posts, а не WP_Query, вам потрібно пройти через suppress_filters => false або це не запустить фільтр. Щоб виконати LIKE на мета-клавіші, вам також потрібно поставити% перед і за ключем у масиві залежно від того, який тип подібного пошуку ви хочете виконати.
Ерл Девіс

І як би ви відфільтрували його, якщо ви хочете запитувати повідомлення, але ВИКЛЮЧИТИ всі повідомлення, що мають мета-ключ повідомлення за префіксом? (напр., виключити всі повідомлення, що мають мета-повідомлення LIKE 'my_prefix_'?
gordie

6

З Wordpress 5.1 тепер можна використовувати мета-запит, наприклад: введіть тут опис зображення


Уникнення підкреслення, здається, є проблемою цього методу, але в іншому випадку це виглядає досить добре. Спасибі за підсвічування.
Джейк

2

Якщо згодом ви хочете розширити це за допомогою більш детальної статистики, функцій тощо, то ще однією альтернативою можуть бути: спеціальні таблиці

  • плюси : з урахуванням ваших потреб і можуть бути проіндексовані для кращої роботи.

  • мінуси : Більше роботи

Також може бути вирішено використання спеціальної таксономії, яка могла б забезпечити кращу ефективність запитів, ніж розміщення мета-запитів, завдяки індексуванню основних таблиць.

Я намагаюся надіслати сповіщення всім, хто сподобався дописом, коли комусь ще подобається цей пост ... щось на кшталт: "Ей, хтось ще любив цю публікацію, яка вам сподобалась. Ви повинні перевірити це!" Але мені потрібен спосіб дізнатися, чи сподобався комусь ще цей пост, і якщо так, то ким би вони були, щоб я міг їх повідомити.

Не впевнені, які саме тут ви маєте на увазі сповіщення, але це може швидко отримати об'ємні.

Приклад : Користувач, якому подобається ~ 1000 публікацій, і кожна публікація отримує ~ 1000 лайків, тоді в повідомленнях є 1М сповіщень, лише для цього користувача! Якщо це сповіщення електронною поштою, то постачальник послуг може не радіти, і користувач зійде з розуму. Це також може бути дорогим стороннім сервісом електронної пошти.


Я фактично надсилаю сповіщення лише один раз на особу за повідомлення. Так що менше, ніж це звучить - хоча все-таки багато. Причина, яку я намагаюся використовувати вбудовані в таблиці, полягає в тому, що я хотів би мати можливість використовувати стандартний API WP REST вниз в реальному додатку з цими даними.
codecribblr

-1

Відповідно до документації WP_Meta_Query ви можете використовувати compareаргумент у meta_queryаргументі WP_Query. Однак ви можете порівнювати лише те, valueа не те, keyщоб ви могли переосмислити, як ви це структуруєте.

likeАргумент буде виглядати наступним чином :

$arguments = array(
    'meta_query' => array(
        array(
            'key' => 'foo',
            'value' => 'ba',
            'compare' => 'LIKE'
        )
    )
);

$query = new WP_Query($arguments);

Зважаючи на те, що ви не можете здійснити пошук "LIKE", keyя б запропонував вам додати вподобані публікації в мета користувача та здійснити пошук WP_User_Query для користувачів, яким сподобалась ця публікація:

$arguments = array(
    'meta_query' => array(
        array(
            'key' => 'liked_post',
            'value' => '<post_id>'
        )
    )
);

$users = new WP_User_Query($arguments);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.