Pregunta

Estoy trabajando en un proyecto en el que estoy creando un tipo de mensaje personalizado y personalizado de los datos introducidos a través de la meta cajas asociadas con mi custom post type.Por alguna razón decidí código de la meta de casillas de tal manera que las entradas en cada metabox son parte de una matriz.Por ejemplo, yo soy el almacenamiento de la longitud y la latitud:

<p> 
    <label for="latitude">Latitude:</label><br /> 
    <input type="text" id="latitude" name="coordinates[latitude]" class="full-width" value="" /> 
</p> 
<p>     
    <label for="longitude">Longitude:</label><br /> 
    <input type="text" id="longitude" name="coordinates[longitude]" class="full-width" value="" /> 
</p>

Por la razón que sea, me gustó la idea de tener una singular postmeta entrada para cada metabox.En el save_post gancho, puedo guardar los datos así:

update_post_meta($post_id, '_coordinates', $_POST['coordinates']);

Hice esto porque tengo tres metaboxes y me gusta tener sólo 3 postmeta valores para cada puesto de trabajo;sin embargo, me he dado cuenta de un problema potencial con este.Puede que desee utilizar WP_Query a sólo tire de determinados puestos de trabajo, basado en estos valores meta.Por ejemplo, puede que desee para obtener todos los mensajes que han latitud valores por encima de 50.Si yo tuviera este tipo de datos en la base de datos de forma individual, tal vez con la tecla latitude, Me gustaría hacer algo como:

$args = array(
    'post_type' => 'my-post-type',
    'meta_query' => array(
        array(
            'key' => 'latitude',
            'value' => '50',
            'compare' => '>'
        )
    )
 );
$query = new WP_Query( $args );

Desde que tengo la latitud como parte de la _coordinates postmeta, esto no iba a funcionar.

Entonces, mi pregunta es, hay alguna manera de utilizar meta_query a la consulta de un array serializado como la que tengo en este escenario?

¿Fue útil?

Solución

No, no es posible, y podría incluso ser peligroso.

Te recomiendo que unserialize sus datos y modificar guardar su rutina.Algo similar a esto debe convertir los datos al nuevo formato:

$args = array(
    'post_type' => 'my-post-type',
    'meta_key' => '_coordinates',
    'posts_per_page' => -1
 );
$query = new WP_Query( $args );
if($query->have_posts()){
    while($query->have_posts()){
        $query->the_post();
        $c = get_post_meta($post->id,'_coordinates',true);
        add_post_meta($post->ID,'_longitude',$c['longitude']);
        add_post_meta($post->ID,'_latitude',$c['latitude']);
        delete_post_meta($post->ID,'_coordinates',$c);
    }
}

Entonces usted será capaz de consulta que se desee con las teclas

Si necesita almacenar varias longitudes, y varias latitudes, puede almacenar varios post meta con el mismo nombre.Simplemente utilice el tercer parámetro de get_post_meta, y regresará todos ellos como una matriz

¿Por qué no Puede Usted Consulta Dentro de Serializado de Datos?

MySQL ve como una cadena, y no puede romperlo en datos estructurados.Romper aparte en datos estructurados es exactamente lo que el código anterior no hace

Usted puede ser capaz de consulta para el parcial de fragmentos de la fecha, pero esto va a ser super fiable, caro, lento y muy frágil, con una gran cantidad de casos de borde.Serial de datos no está pensado para las consultas SQL, y no está formateado de una manera regular y constante.

Además de los costos de la cadena parcial de las búsquedas, correos meta consultas son lentos, y serializada de los datos pueden cambiar dependiendo de cosas como la duración de los contenidos, haciendo que la búsqueda increíblemente caro, si no imposible, dependiendo del valor que se está buscando

Una Nota sobre el Almacenamiento de los Registros/Entidades/Objetos como Objetos Serializados en el Meta

Puede almacenar un registro de transacciones en el poste de meta, o algún otro tipo de estructura de datos en la que el usuario meta, a continuación, ejecute en el problema anterior.

Aquí la solución no es dividirlo en cada poste de meta, pero para darse cuenta de que nunca debería haber sido de meta, para empezar, pero un tipo de mensaje personalizado.Por ejemplo, un registro o el registro de un tipo de mensaje personalizado, con el post original como un padre, o se unieron a través de una taxonomía plazo

La seguridad y los Objetos Serializados

El almacenamiento de PHP serializado objetos a través de la serialize la función puede ser peligroso, lo cual es lamentable, ya que pasa de un objeto a WordPress significará se pone serializado.Esto es debido a que cuando el objeto es de la serie, se crea un objeto, y todos sus despertador métodos y constructores se ejecuta.Esto puede no parecer una gran cosa hasta que un usuario se las arregla para colarse un cuidadosamente elaborado, de entrada, que conduce a la ejecución remota de código cuando se leen los datos de la base de datos y de serializado por WordPress.

Esto puede evitarse mediante el uso de JSON en lugar de eso, que también hace las consultas más fácil, pero es mucho más fácil/rápido sólo para almacenar los datos correctamente y evitar estructurado de datos serializados, para empezar.

Otros consejos

Yo también funcionan en esta situación.Aquí lo que hice:

$args = array(
    'post_type' => 'my-post-type',
    'meta_query' => array(
        array(
            'key' => 'latitude',
            'value' => sprintf(':"%s";', $value),
            'compare' => 'LIKE'
        )
    )
);

Espero que esta ayuda

Usted realmente va a perder la capacidad para la consulta de sus datos en cualquier manera eficiente, cuando serializar las entradas en la base de datos de WP.

El rendimiento global de ahorro y la ganancia que creo que se está logrando mediante la serialización no va a ser perceptible a cualquier medida.Usted puede obtener un poco más pequeño tamaño de base de datos, pero el costo de las transacciones de SQL va a ser pesado si alguna vez consulta de los campos y tratar de compararlos en cualquier útil, significativo manera.

En su lugar, guardar la serialización de datos que no tiene intención de consulta en la que la naturaleza, sino sólo de acceso en una forma pasiva de la moda por la directa WP llamada a la API get_post_meta() - a partir de la función que se puede desempaquetar serializado de entrada para acceder a sus propiedades de matriz demasiado.

De hecho le asigna el valor de cierto como en;

$meta = get_post_meta( $post->ID, 'key', true );

Devolverá los datos como una matriz, accesible para recorrer de forma normal.

Usted puede concentrarse en otra base de datos/sitio optimizaciones como el almacenamiento en caché, CSS y JS minificación y el uso de servicios tales como un CDN si se requiere.Al nombre pero a algunos....Codex de WordPress es un buen punto de partida para descubrir más sobre este tema: AQUÍ

Acabo tratada con serializado campos y podría consultar.No usar el meta_query pero el uso de una consulta SQL.

global $wpdb; 

$search = serialize('latitude').serialize(50);

$query = $wpdb->prepare("SELECT `post_id`
FROM `wp_postmeta`
WHERE `post_id` IN (SELECT `ID` FROM `wp_posts` WHERE `post_type` = 'my-post-type')
AND `meta_key` = '_coordinates'
AND `meta_value` LIKE '%s'",'%'.$search.'%');

$ids = $wpdb->get_col($query);

$args = array(
    'post__in' => $ids
    'post_type' => 'team' //add the type because the default will be 'post'
);

$posts = get_posts($args);

La consulta busca primero post con el mismo post_type por lo que la cantidad de wp_postmeta registros serán menos de filtro.Luego he añadido un lugar de instrucción para reducir las filas más por el filtrado en meta_key

El Id de terminar bien en una matriz como sea necesario para get_posts.

PS.MySQL v5.6 o más es necesario para el buen rendimiento de la subconsulta

Este ejemplo realmente me ayudó.Es específicamente para S2Members plugin (que serializa los metadatos del usuario).Pero le permite a la consulta de una parte de un array serializado en la meta_key.

Funciona mediante el uso de MySQL, el REGEXP función.

Aquí es la fuente

Aquí está el código que las consultas de todos los usuarios que viven en los estados unidos.Yo fácilmente modificado para consulta de uno de mis personalizado campos de registro y había que trabajar en ningún momento.

  <?php
global $wpdb;
$users = $wpdb->get_results ("SELECT `user_id` as `ID` FROM `" . $wpdb->usermeta . 
          "` WHERE `meta_key` = '" . $wpdb->prefix . "s2member_custom_fields' AND 
           `meta_value` REGEXP '.*\"country_code\";s:[0-9]+:\"US\".*'");
if (is_array ($users) && count ($users) > 0)
    {
        foreach ($users as $user)
            {
                $user = /* Get full User object now. */ new WP_User ($user->ID);
                print_r($user); /* Get a full list of properties when/if debugging. */
            }
    }
?>

Creo que hay 2 soluciones que puede tratar de resolver el problema de los resultados se almacenan como tanto de cadenas y Enteros.Sin embargo, es importante decir que, como otros señalaron que no es posible garantizar la integridad de los resultados almacena como un Entero, porque, como estos valores almacenados como en serie de matrices, el índice y los valores se almacenan exactamente con el mismo patrón.Ejemplo:

array(37,87);

se almacena como un array serializado, como este

a:2:{i:0;i:37;i:1;i:87;}

Nota la i:0 como la primera posición de la matriz y i:37 como el primer valor.El patrón es el mismo.Pero vayamos a las soluciones


1) REGEXP Solución

Esta solución funciona para mí, independientemente de la meta valor se guarda como cadena o número / id.Sin embargo, se utiliza REGEXP, que no es tan rápido como el uso de LIKE

$args = array(
    'post_type' => 'my-post-type',
    'meta_query' => array(
        array(
            'key' => 'latitude',
            'value' => '\;i\:' . $value . '\;|\"' . $value . '\";',
            'compare' => 'REGEXP'
        )
    )
);

2) COMO Solución

No estoy seguro acerca de la diferencia de rendimiento, pero esta es una solución que utiliza LIKE y también funciona para ambos, número de cuerdas y

 $args = array(
        'post_type' => 'my-post-type',
        'meta_query' => array(
            'relation' => 'OR',
            array(
                'key' => 'latitude',
                'value' => sprintf(':"%s";', $value),
                'compare' => 'LIKE'
            ),
            array(
                'key' => 'latitude',
                'value' => sprintf(';i:%d;', $value),
                'compare' => 'LIKE'
            )
        )
    );

Después de leer un montón de consejos para ejecutar un WP_Query filtrando por serializado matrices, aquí es cómo finalmente lo hice:mediante la creación de una matriz de valores separados por comas mediante implosión en conjunción con un $wpdb consulta SQL personalizada utilizando FIND_IN_SET para buscar la lista separada por comas para el valor requerido.

(esto es similar a Tomas la respuesta, pero es un poco menos de rendimiento intensivo de la consulta SQL)

1.En functions.php:

En su functions.php archivo (o donde sea que usted está configurando el meta del cuadro) en el yourname_save_post() el uso de la función

update_post_meta($post->ID, 'checkboxArray', implode(",", $checkboxArray)); //adding the implode

para crear la matriz que contiene valores separados por comas.

Usted también querrá a cambio de la variable de salida en la yourname_post_meta() admin meta cuadro de construcción de la función a

$checkboxArray = explode(",", get_post_custom($post->ID)["checkboxArray"][0]); //adding the explode

2.En la plantilla de archivo PHP:

Prueba:si ejecuta un get_post_meta( $id ); usted debe ver checkboxArray como una matriz que contiene sus valores separados por comas en lugar de un array serializado.

Ahora, vamos a construir nuestro personalizada de consultas SQL utilizando $wpdb.

global $wpdb;

$search = $post->ID;

$query = "SELECT * FROM wp_posts
          WHERE FIND_IN_SET( $search, (
              SELECT wp_postmeta.meta_value FROM wp_postmeta
              WHERE wp_postmeta.meta_key = 'blogLocations'
              AND wp_postmeta.post_id = wp_posts.ID )
          )
          AND ( wp_posts.post_type = 'post' )
          AND ( wp_posts.post_status = 'publish' );";

$posts = $wpdb->get_results($query);

foreach ($posts as $post) {
    //your post content here
}

El aviso FIND_IN_SET, que es donde ocurre la magia.

Ahora...ya estoy usando SELECT * esto devuelve todos los datos de envío y dentro de la foreach usted puede eco de lo que usted desea de que (hacer un print_r($posts); si usted no sabe lo que está incluido.No configura "el bucle" for you (yo lo prefiero de esta manera), pero puede ser fácilmente modificado para configurar el bucle si usted prefiere (echa un vistazo a setup_postdata($post); en el codex, usted probablemente tendrá que cambiar SELECT * para seleccionar sólo el ID del post y $wpdb->get_results para la correcta $wpdb tipo -- ver el codex para $wpdb también para obtener información sobre que sujeto).

Cachorro, tomó un poco de esfuerzo, pero desde wp_query no admite haciendo 'compare' => 'IN' serializada o valores separados por comas esta cuña es su mejor opción!

Espero que esto ayude a alguien.

Si utiliza el like operador de comparación en su meta de consulta, debería funcionar bien para mirar dentro de un array serializado.

$wp_user_search = new WP_User_Query(array(
    'meta_query' => array(
        array(
            'key'     => 'wp_capabilities',
            'value'   => 'subscriber',
            'compare' => 'not like'
            )
        )
    )
);

resultados en:

[query_where] => WHERE 1=1 AND (
  ( wp_usermeta.meta_key = 'wp_capabilities' 
  AND CAST(wp_usermeta.meta_value AS CHAR) NOT LIKE '%subscriber%' )

Si mi meta datos es de tipo matriz, estoy usar este método para consulta por meta:

$args = array(
    'post_type' => 'fotobank',
    'posts_per_page' => -1,
    'meta_query' => array(
            array(
                   'key' => 'collections',
                   'value' => ':"'.$post->ID.'";',
                   'compare' => 'LIKE'
            )
     )
);
$fotos = new WP_Query($args);

Tengo curiosidad acerca de las respuestas de arriba, donde el meta_query dirigido a la clave latitude en lugar de _coordinates.Tenía que ir y probar si realmente era posible en meta consultas dirigirse a una clave específica dentro de un array serializado.:)

Que obviamente no era el caso.

Así, tenga en cuenta que la correcta clave de objetivo es _coordinates en lugar de latitude.

$args = array(
     'post_type' => 'my-post-type',
     'meta_query' => array(
         array(
             'key' => '_coordinates',
             'value' => sprintf(':"%s";', $value),
             'compare' => 'LIKE'
         )
     )
 );

NOTAS:

  1. Este enfoque hace sólo lo que es posible destino coincidencias exactas.Así que cosas como todas las latitudes de más de 50 no son posibles.

  2. Para incluir subcadena partidos, uno podría usar 'value' => sprintf(':"%%%s%%";', $value),.(no lo he probado)

Tengo la misma pregunta.Tal vez usted necesita el 'tipo' de parámetro?Echa un vistazo a este interrogante:Campo personalizado de Consulta - Valor Meta es la Matriz de

Tal vez probar:

    $args = array(
    'post_type' => 'my-post-type',
    'meta_query' => array(
        array(
            'key' => 'latitude',
            'value' => '50',
            'compare' => '>',
            'type' => 'numeric'
        )
    )
    );

Me he topado con algo similar, mientras que el uso de la Magia de los Campos de plugin.Esto podría hacer el truco

$values_serialized = serialize(array('50'));
$args = array(
    'post_type' => 'my-post-type',
    'meta_query' => array(
        array(
            'key' => 'latitude',
            'value' => $values_serialized,
            'compare' => '>'
        )
    )
);
Licenciado bajo: CC-BY-SA con atribución
scroll top