Como posso criar uma meta_query com uma matriz como meta_field?

12

Aqui estão os argumentos para minha consulta:

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

Isso funciona quando topics é uma string, mas não é quando é uma matriz. Gostaria que esta consulta funcionasse quando topics é, por exemplo, array( 'sports', 'nonprofit', etc. )

Existe uma maneira de criar meta-consultas com matrizes como meta_key?

    
por mike23 15.06.2012 / 15:04

5 respostas

22

Alimentando a consulta com uma matriz de possíveis valores

Se o valor no banco de dados for uma string e você quiser alimentar vários valores à consulta:

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

Procurando por um valor específico em uma matriz serializada de dados

Se o valor no banco de dados for uma matriz de vários tópicos e você quiser procurar um único tópico dentro dessa matriz (Observe que uma matriz no banco de dados pode ser recuperada como tal, mas reside no banco de dados em forma serializada, que é uma string também):

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

Usando "LIKE", como o valor de comparação não é tão nítido quanto uma instrução como você poderia esperar, mas é a melhor opção para seguir.

Além disso, sua única outra opção seria recuperar todas as postagens que têm os meta_key "tópicos" definidos e iterá-los manualmente ou, em outras palavras, verificar o valor dentro do loop e exibir os posts na referida condição.

    
por Johannes Pille 15.06.2012 / 16:27
11

Para sair da resposta de Johannes, já que é uma matriz serializada, se você estiver armazenando algo como id do usuário (que era o meu caso), talvez seja necessário lidar com isso de maneira um pouco diferente.

Post meta estava sendo salvo como:

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

Então, sim, eles são inteiros, mas através de update_post_meta eles estavam sendo salvos como strings.

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

Então, você está realmente fazendo uma comparação LIKE com a versão de string serializada do que está procurando. Passei umas boas horas tentando fazer algo assim funcionar e até agora isso foi o melhor que consegui fazer.

    
por sMyles 06.06.2015 / 05:09
2

Outra pequena melhora na resposta do @sMyles.

Eu tive casos em que as IDs foram armazenadas como strings (como quando obtidas de uma entrada de formulário) e como números inteiros (por exemplo, update_post_meta($post_id, authorized_users', array(get_current_user_id())); ). Este é um tipo de problema bem conhecido com wp_set_object_terms() , onde você pode usar IDs de termo para definir os termos, mas se você não os converter como números inteiros, você terá 50% de chance de criar novos termos com esses números como seus nomes.

Isso pode fazer com que eles sejam armazenados de forma bastante diferente em um array serializado, como pode ser visto nos trechos de um caso desse tipo no banco de dados do meu site de teste:

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

Ambos os itens acima, quando alimentados com print_r() serão renderizados como

Array
(
    [0] => 1
)

Para corrigir isso, fiz um ligeiro ajuste ao meta_query adicionando uma relation e outra versão da consulta que atribui o valor como um inteiro em vez de uma string.

Este é o resultado final:

        '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: Acabamos de perceber que esse método poderia correr o risco de colisões com índices de matriz, o que poderia permitir acesso ilegal a materiais se eles não estivessem no array, mas seu ID de usuário aparecesse como Um índice. Assim, enquanto isso funciona se você tiver o problema discutido, a melhor prática é garantir que todos os valores que você deseja pesquisar sejam convertidos como sequências de caracteres antes de salvá-los, para que você possa usar o método @sMyles em vez disso.

    
por Kaji 13.07.2018 / 04:44
1

Eu iria para a resposta de Johannes. No entanto, eu quero melhorar isso porque usando esse meta_query, você encontrará um caso como este

seu valor é

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

quando você pesquisa

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

o resultado retornará "sport" e "sport2".

Para corrigir isso, altere os argumentos meta_query para

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

É porque o valor é serializado no banco de dados e cada item será separado por ponto e vírgula. Assim, os argumentos acima funcionarão

Se os itens no valor forem numéricos, você só precisa remover as aspas duplas "

$args = array(
        'post_type' => 'news',
        'meta_query' => array(
            array(
                'key' => 'topics',
                'value' => '1;',
                'compare' => 'LIKE'
            )
        )
    );
    
por Ha Doan Ngoc 02.11.2016 / 09:22
0

Eu me encarei com algo parecido hoje. Eu tenho que consultar um campo de relacionamento ACF (Advanced Custom Fields) com vários usuários relacionados (matriz).

Após atualizar o campo via php, a consulta não funcionou. Depois de atualizá-lo através da interface do usuário do ACF, a consulta funcionou.

O problema era que o meu código php definia os valores de relacionamento como int-values, a interface do usuário o definia como string-values. Para ter certeza de que ambos funcionam, eu uso esta consulta agora (ajustada ao exemplo aqui):

$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'
        ),
    )
);
    
por Julian Stark 06.07.2018 / 08:22