¿Usar post__in y post__not_in juntos?

2 ago 2013, 05:13:30
Vistas: 22.6K
Votos: 1

Estoy tratando de mostrar solo las entradas que un usuario no ha visto, de esta manera:

$exclude = array(1,2,3);
$include = array(3,4,5);
$args = array(
  'post_type'           => 'post',
  'post_status'         => 'publish',
  'posts_per_page'      => 30,
  'post__in'            => $include,
  'post__not_in'        => $exclude,
  'orderby'             => 'post__in',            
  'tax_query'           => array(
        'relation' => 'AND',
         array(
            'taxonomy'  => 'category',
            'field'     => 'slug',
            'terms'     => array($category_names),
            'operator'  => 'IN'
         ),
         array(
            'taxonomy'  => 'category',
            'field'     => 'ID',
            'terms'     => array($category_ids),
            'operator'  => 'NOT IN'
         )
  )
);
$posts = get_posts($args);

Esperaría que esto devolviera las entradas 4 y 5, pero devuelve 3, 4 y 5.

¿Cómo establezco qué parámetro tiene preferencia entre 'post__in' y 'post__not_in'?

Sé que podría usar array_diff() en las variables $exclude y $include, pero la realidad es más complicada que esta pregunta. Tengo muchos arrays diferentes para comparar, y algunos de ellos son multidimensionales. También estoy incluyendo y excluyendo ciertas taxonomías.

También creo que es más fácil para otros leer si es una llamada WP_Query o $wpdb, en lugar de líneas y líneas de PHP para terminar con un parámetro de consulta.

Además, si array_diff es igual a un array vacío, entonces la consulta realmente devuelve entradas, no nada.

Entonces, ¿quizás la mejor manera sea una llamada $wpdb, o una forma de usar meta_query de WP_Query en el campo ID de la entrada?

4
Comentarios

¿Podrías explicar la complicada realidad, por favor?

s_ha_dum s_ha_dum
2 ago 2013 06:13:38

Actualizado para explicar por qué prefiero no usar array_diff si es posible. Creo que un enfoque con $wpdb podría ser el mejor.

Drew Baker Drew Baker
2 ago 2013 08:22:19

@DrewBaker Todavía no entiendo una cosa. Dices: Tengo muchos arrays diferentes para comparar, y algunos de ellos son multidimensionales Pero para usar include y exclude debes pasar un array plano de ids. ¿Entonces haces alguna lógica para extraer dos arrays planos de los arrays diferentes y multidimensionales? Si es así, podrías ejecutar array_diff y si el resultado está vacío podrías usar un if y nunca ejecutar la consulta, $posts = ! empty($diff) ? get_posts($args) : array();

gmazzap gmazzap
2 ago 2013 12:40:56

OK, entiendo lo que están diciendo. Usaré array_diff(). ¡Gracias!

Drew Baker Drew Baker
2 ago 2013 20:18:19
Todas las respuestas a la pregunta 2
2

post__in y post__not_in son mutuamente excluyentes.

Nota: no puedes combinar post__in y post__not_in en la misma consulta.

http://codex.wordpress.org/Class_Reference/WP_Query

Tal como está escrita tu pregunta, la solución que rechazas (la de usar array_diff) es la respuesta obvia.

Si es cierto que esa solución no funciona, necesitarás un filtro en posts_where (probablemente) que proporcione la lógica de consulta que necesitas. Como no has explicado "la realidad [que] es más complicada que esta pregunta", realmente no es posible adivinar cuál podría ser esa lógica.

Pero aquí hay un ejemplo de un filtro posts_where:

function smbd_cats_by_days ($where = '') {
    // global $days_limit; // si es una variable
    // $days_limit = DAYS_LIMIT; // si es una constante
    // $days_limit = get_option('days_limit',100);
    // tienes que descomentar una de las líneas anteriores,
    // dependiendo de tu elección de mecanismos
    $where .= " AND post_date < '" . date('y-m-d', strtotime("-{$days_limit} days")) . "'";
    return $where;
}
add_filter('posts_where', 'smbd_cats_by_days');

Basado en la edición de la pregunta y en esta declaración de intención:

Estoy intentando mostrar solo publicaciones que un usuario no ha visto...

Escribe el PHP para crear un array de publicaciones que el usuario ha visto y exclúyelas con post__not_in. Tu intento de meter todo en la consulta solo está complicando las cosas.

También creo que es más fácil de leer para otros si es una WP_Query o una llamada $wpdb, en lugar de líneas y líneas de PHP para terminar con un parámetro de consulta.

Para cuando escribas los filtros o el SQL para incluir todo en la consulta, no será más "legible" y es cuestionable si sería más legible en primer lugar. Estás intentando hacer esto de la manera difícil. WP_Query no es capaz de lógica compleja y la lógica compleja en SQL es difícil de escribir y difícil de leer incluso en un buen día.

2 ago 2013 06:25:02
Comentarios

o tal vez un posts_join http://codex.wordpress.org/Plugin_API/Filter_Reference/posts_join

gmazzap gmazzap
2 ago 2013 06:29:52

Gracias, lo entiendo. Usaré array_diff() entonces. Gracias. He votado a favor de esta respuesta ya que te esforzaste en responder mi mala pregunta.

Drew Baker Drew Baker
2 ago 2013 20:19:02
4

Exclude e include no pueden usarse juntos, este código se utiliza en el núcleo, por lo que es uno o el otro.

...
if ( ! empty($r['include']) ) {
  $incposts = wp_parse_id_list( $r['include'] );
  $r['posts_per_page'] = count($incposts);  // solo el número de posts incluidos
  $r['post__in'] = $incposts;
} elseif ( ! empty($r['exclude']) )
...

Una consulta $wpdb es fácil si los únicos argumentos que necesitas son solo los que has publicado.

Esta forma es fácil, pero ¿puedes explicar por qué no se puede hacer de otra manera?

$exclude = array(1,2,3);
$include = array(3,4,5);
$args = array(
    'post_type'         => 'post',
    'post_status'       => 'publish',
    'posts_per_page'    => 30,
    'post__in'          => array_diff($include, $exclude),
)
$posts = get_posts($args);
2 ago 2013 05:40:23
Comentarios

Sé que podría usar array_diff() en las variables $exclude y $include, pero la realidad es más complicada que esta pregunta. Debe hacerse en la consulta.

s_ha_dum s_ha_dum
2 ago 2013 06:11:43

@s_ha_dum Lo siento, error mío. Vota negativo la respuesta, no puedo hacerlo yo.

gmazzap gmazzap
2 ago 2013 06:13:02

Actualicé la consulta para reflejar todos los parámetros que estoy usando. Una consulta con $wpdb podría ser la mejor opción.

Drew Baker Drew Baker
2 ago 2013 08:29:26

Estaba confundido sobre por qué mi consulta no funcionaba hasta que leí el Codex acerca de WP_Query. Solo puedes usar post__in o post__not_in. No ambos juntos en la misma consulta. Encontré esta solución, y debo decir que es una solución alternativa genial.

Michael Ecklund Michael Ecklund
1 nov 2017 18:15:43