¿Cómo puedo crear una meta_query con una matriz como meta_field?

12

Aquí están los argumentos para mi consulta:

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

Esto funciona cuando topics es una cadena, pero no cuando es una matriz. Me gustaría que esta consulta funcione cuando topics es, por ejemplo, array( 'sports', 'nonprofit', etc. )

¿Hay alguna forma de crear metadetecas con matrices como una meta_key?

    
pregunta mike23 15.06.2012 - 15:04

5 respuestas

22

Alimentando a la consulta una matriz de valores posibles

Si el valor en la base de datos es una cadena y desea alimentar la consulta con varios valores:

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

Buscando un valor específico en una matriz de datos serializada

Si el valor en la base de datos es una matriz de varios temas y desea buscar un solo tema dentro de esa matriz (tenga en cuenta que una matriz en la base de datos puede recuperarse como tal, pero vive en la base de datos en forma serializada). que es una cadena también):

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

Usar 'LIKE' como valor de comparación no es una instrucción tan clara como podría haber esperado, pero es la mejor opción para ir con.

Además de eso, su única otra opción sería recuperar todas las publicaciones que tengan los "temas" de meta_key configurados e iterarlos manualmente o, en otras palabras, verificar el valor dentro del bucle y mostrar los mensajes en dicha condición.

    
respondido por el Johannes Pille 15.06.2012 - 16:27
11

Para dejar de lado la respuesta de Johannes, ya que es una matriz serializada, si está almacenando algo como el ID de usuario (que fue mi caso), es posible que deba manejarlo de manera un poco diferente.

La meta del mensaje se estaba guardando como:

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

Entonces, sí, son enteros pero a través de update_post_meta se guardaron como cadenas.

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

Entonces, en realidad estás haciendo una comparación LIKE con la versión de serie serializada de lo que estás buscando. Pasé un par de horas tratando de hacer que algo así funcionara y hasta ahora esto fue lo mejor que pude encontrar.

    
respondido por el sMyles 06.06.2015 - 05:09
2

Otra ligera mejora con respecto a la respuesta de @sMyles.

He tenido casos en los que los ID se han almacenado tanto como cadenas (como cuando se toman de una entrada de formulario) y como enteros (por ejemplo, update_post_meta($post_id, authorized_users', array(get_current_user_id())); ). Esto es algo así como el conocido problema con wp_set_object_terms() , donde puedes usar los ID de los términos para establecer los términos, pero si no los conviertes como enteros primero tienes una probabilidad del 50% de crear nuevos términos con esos números. como sus nombres en su lugar.

Esto puede hacer que se almacenen de manera muy diferente en una matriz serializada, como se puede ver en los extractos de un caso de este tipo de la base de datos del sitio de prueba:

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

Tanto de lo anterior, cuando se alimenta a través de print_r() se procesará como

Array
(
    [0] => 1
)

Para solucionar esto, realicé un pequeño ajuste al meta_query al agregar un relation y otra versión de la consulta que convirtió el valor como un número entero en lugar de una cadena.

Aquí está el 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: Me di cuenta de que este método podría correr el riesgo de colisiones con los índices de matriz, lo que podría permitir el acceso ilícito a los materiales si no están en la matriz, pero su ID de usuario aparece como un índice. Como tal, mientras este funciona si tiene el problema tratado, lo mejor es asegurarse de que los valores que desea buscar se emitan como cadenas antes de guardarlos para poder usar el método de @sMyles en su lugar.

    
respondido por el Kaji 13.07.2018 - 04:44
1

Iría por la respuesta de Johannes. Sin embargo, quiero mejorar eso porque al utilizar esa meta_query, encontrarás un caso como este

tu valor es

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

cuando buscas

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

entonces el resultado devolverá 'sport' y 'sport2'.

Para arreglar eso, cambia los argumentos meta_query a

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

Se debe a que el valor se serializa en la base de datos y cada elemento se separará con un punto y coma. Por lo tanto, encima de args funcionará

Si los elementos en el valor son números, solo necesita eliminar la comilla doble "

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

Me peleé con algo similar hoy. Tengo que consultar un campo de relación ACF (Campos personalizados avanzados) con varios usuarios relacionados (matriz).

Después de actualizar el campo a través de php, la consulta no funcionó. Después de actualizarlo a través de la interfaz de usuario de ACF, la consulta funcionó.

El problema fue que mi código php configuró los valores de la relación como valores int, la IU lo estableció en valores de cadena. Para asegurarme de que ambos funcionen, ahora uso esta consulta (ajustada al ejemplo aquí):

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

Lea otras preguntas en las etiquetas