Як я можу створити мета_запит з масивом як meta_field?


16

Ось аргументи для мого запиту:

$args = array(
    'post_type' => 'news',
    'meta_query' => array(
        array(
            'key' => 'topics',
            'value' => 'sports',
        )
    )
);

Це працює, коли topicsце рядок, але не, коли це масив. Я хотів би, щоб цей запит працював, коли topicsє, наприкладarray( 'sports', 'nonprofit', etc. )

Чи є спосіб побудувати мета-запити з масивами як meta_key?


Поясніть, будь ласка, ви маєте на увазі, що збережене значення "теми" є масивом? Або що збережене значення - це рядок, і ви хочете передати кілька запитів запиту в масиві?
MathSmath

@MathSmath, я маю на увазі, що збережене значення - це масив.
mike23

Відповіді:


31

Подання запиту масивом можливих значень

Якщо значення в базі даних є рядком, і ви хочете подати запит декількома значеннями:

$args = array(
    'post_type' => 'news',
    'meta_query' => array(
        array(
            'key' => 'topics',
            'value' => array ( 'sports', 'nonprofit', 'community' ),
            'compare' => 'IN'
        )
    )
);

Пошук конкретного значення в серіалізованому масиві даних

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

$args = array(
    'post_type' => 'news',
    'meta_query' => array(
        array(
            'key' => 'topics',
            'value' => 'sports',
            'compare' => 'LIKE'
        )
    )
);

Використання "LIKE" як значення порівняння не настільки чітка інструкція, як ви могли сподіватися, але це найкращий варіант.

Поруч із цим, вашим єдиним іншим варіантом буде отримання всіх повідомлень, у яких встановлено "теми" meta_key, та повторення вручну над ними, або, іншими словами, перевірити значення в циклі та відобразити повідомлення у зазначеному стані.


14

Щоб відмовитись від відповіді Йоганнеса, оскільки це серіалізований масив, якщо вам трапляється зберігати щось на зразок ідентифікатора користувача (що було в моєму випадку), можливо, вам доведеться обробити це трохи інакше.

Мета публікації зберігалася так:

array( "1", "23", "99");

Так, так, вони є цілими числами, але через update_post_metaних вони зберігаються як рядки.

'meta_query' => array(
            array(
                    'key'     => 'my_meta_key',
                    'value'   => serialize( strval( 1 ) ),
                    'compare' => 'LIKE'
                )
            )

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


serialize (strval (1)) вирішив мою проблему, спасибі
Бехзад

Сьогодні випадкова відповідь натрапила випадково. Мені подобається ваше доповнення. +1
Йоганнес Піл

Я також просто натрапив на це, моя річ полягає в тому, що мені потрібно отримати всі повідомлення, де user_id не знаходиться в масиві, але вищевказане рішення не працює, тому я зробив це так: 'meta_query' => array( array( 'key' => 'my_meta_key', 'value' => ':' . $user_id . ';', 'compare' => 'NOT LIKE' ) ) Тому що при серіалізації всі значення зберігаються на зразок: ' : значення; '
Бобз

4

Ще одне незначне покращення від відповіді @sMyles.

У мене були випадки, коли ідентифікатори зберігалися як у вигляді рядків (наприклад, узятих із введення форми), так і у вигляді цілих чисел (наприклад update_post_meta($post_id, authorized_users', array(get_current_user_id()));). Це схоже на добре відому проблему, з якою wp_set_object_terms()ви можете використовувати ідентифікатори термінів для встановлення термінів, але якщо ви не призначите їх як цілі числа, ви маєте приблизно 50% шансів створити нові терміни з цими числами як їх імена замість цього.

Це може призвести до того, що вони зберігаються зовсім інакше в серіалізованому масиві, як видно з уривків саме такого випадку з бази даних мого тестового сайту:

a:1:{i:0;s:1:"1";} // 's' for 'string', also note the double quotes
a:1:{i:0;i:1;} // 'i' for 'integer', no quotes

І те і інше, коли буде подано через, print_r()буде видано як

Array
(
    [0] => 1
)

Щоб виправити це, я зробив невеликий твір до параметра meta_query, додавши ще relationта іншу версію запиту, яка передає значення як ціле число замість рядка.

Ось кінцевий результат:

        'meta_query' => array(
            'relation' => 'OR', // Lets it know that either of the following is acceptable
            array(
                'key' => 'bcm_enm_authorized_users',
                'value'   => serialize(strval(get_current_user_id())), // Saved as string
                'compare' => 'LIKE'
            ),
            array(
                'key' => 'bcm_enm_authorized_users',
                'value'   => serialize(intval(get_current_user_id())), // Saved as integer
                'compare' => 'LIKE'
            ),
        ),

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


Це повинна бути обрана відповідь, найнадійніша
Амін

2

Я б пішов на відповідь Йоганнеса. Однак я хочу вдосконалити це, оскільки використовуючи цей мета-запит, ви зустрінете такий випадок

ваша цінність

array('sports','movies', 'sports2');

під час пошуку

$args = array(
    'post_type' => 'news',
    'meta_query' => array(
        array(
            'key' => 'topics',
            'value' => 'sports',
            'compare' => 'LIKE'
        )
    )
);

тоді результат поверне і «спорт», і «спорт2».

Щоб виправити це, змініть аргументи meta_query на

$args = array(
    'post_type' => 'news',
    'meta_query' => array(
        array(
            'key' => 'topics',
            'value' => 'sports";',
            'compare' => 'LIKE'
        )
    )
);

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

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

$args = array(
        'post_type' => 'news',
        'meta_query' => array(
            array(
                'key' => 'topics',
                'value' => '1;',
                'compare' => 'LIKE'
            )
        )
    );

1

Я сьогодні стикався з чимось подібним. Мені потрібно запитувати поле відносин ACF (Advanced Custom Fields) з ​​кількома пов'язаними користувачами (масив).

Після оновлення поля через php запит не працював. Після його оновлення через інтерфейс ACF запит спрацював.

Проблема полягала в тому, що мій php-код встановив значення співвідношення як int-значення, а інтерфейс встановив його на строкові значення. Щоб переконатися, що обидві працюють, я зараз використовую цей запит (пристосований до прикладу тут):

$args = array(
    'post_type' => 'news',
    'meta_query' => array(
        'relation' => 'OR',
        array(
            'key' => 'topics',
            'value' => '1;',  // works for int-array
            'compare' => 'LIKE'
        ),
        array(
            'key' => 'topics',
            'value' => '"1"',  // works for string-array
            'compare' => 'LIKE'
        ),
    )
);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.