web-dev-qa-db-fra.com

Requête sur le nombre de champs personnalisés?

J'ai le code suivant:

            <div id="pc" class="smartbar-content">
            <ul class="smartbar-items">
            <?php
            $paged = ( get_query_var('paged') ) ? get_query_var('paged') : 1;
            query_posts( array(
                        'cat' => '6', 
                        'posts_per_page' => 5,
                        'meta_key' => 'krit_karakter',
                        'orderby'=> 'menu_order',
                        'order'=> 'DESC',
                        'caller_get_posts' => 1, 
                        'paged' => $paged ) );
                    if (have_posts()) : while (have_posts()) : the_post(); ?>
                    <li><a href="<?php the_permalink(); ?>"><img src="<?php bloginfo('url');?>/wp-content/files_mf/<?php get_custom_field('game_poster', TRUE); ?>" width="80" height="110" alt="<?php the_title();?>" /> </a>
                    <br /><?php the_title();?></a></li>

                    <?php endwhile; ?>
                    <?php else : endif; ?>
            </ul>
            <?php wp_reset_query(); ?>
        </div>

Je souhaite afficher uniquement les publications comportant au moins 5 entrées dans le champ personnalisé "krit_karakter".

Est-ce possible?

1
Martin-Al

Le code suivant vous permet d'ajouter les paramètres wpse4528_key et wpse4528_minimum à vos requêtes, puis ajoutera un critère supplémentaire à la clause where qui compte le nombre de métadonnées avec votre clé.

add_filter( 'posts_where', 'wpse4528_posts_where', 10, 2 );
function wpse4528_posts_where( $where, &$wp_query )
{
    global $wpdb;
    $count_key = $wp_query->get( 'wpse4528_key' );
    if( $count_key ) {
        $where .= $wpdb->prepare( " AND (SELECT COUNT(*) FROM {$wpdb->postmeta} WHERE {$wpdb->postmeta}.post_id = {$wpdb->posts}.ID AND {$wpdb->postmeta}.meta_key = %s) >= %d", $count_key, $wp_query->get( 'wpse4528_minimum' ) );
    }
    return $where;
}
1
Jan Fabry

Vous devez utiliser le filtre posts_groupby à deux reprises. Ils vont probablement ressembler à quelque chose comme ça:

function add_my_groupby($groupby, &$query) {
  global $wpdb;
  $groupby .= "$wpdb->posts.ID";
  return $groupby;
}

function add_my_having($groupby, &$query) {
  $groupby .= " HAVING COUNT(*) >= 5";
  return $groupby;
}

Ensuite, vous devez faire quelque chose comme ça dans votre modèle:

add_filter('posts_groupby', 'add_my_groupby', 10, 2);
add_filter('posts_groupby', 'add_my_having', 1000000, 2);

query_posts( array(/* your stuff...*/) );

remove_filter('posts_groupby', 'add_my_groupby', 10);
remove_filter('posts_groupby', 'add_my_having', 1000000);

(Notez le très grand nombre passé pour la priorité du second filtre. Il est censé contourner le manque de filtre posts_having dans l'API WP.)

Sinon, ne vous embêtez pas avec la corbeille query_posts () et interrogez directement la base de données, par exemple:

$wpdb->get_results("
  SELECT posts.*
  FROM $wpdb->posts as posts
  JOIN $wpdb->postmeta as postmeta
  ON postmeta.post_id = posts.ID
  AND postmeta.meta_key = 'whatever'
  GROUP BY posts.ID
  HAVING COUNT(*) >= 5
  ORDER BY posts.post_date DESC
  LIMIT 5
");

Mise à jour: Comme le fait remarquer Jan, il devrait s'agir de: HAVING COUNT(DISTINCT postmeta.post_id) >= 5 au cas où il y aurait d'autres jointures.

1
Denis de Bernardy

Dois-je comprendre que vous stockez une sorte de tableau dans un champ personnalisé?

Les tableaux sont sérialisés (convertis en texte brut) lorsque WordPress les stocke dans une base de données. Puisque la requête fonctionne au niveau de MySQL, elle ne peut exécuter aucune opération significative sur de telles données sérialisées.

Ce que vous pouvez faire est de stocker le nombre (valeur non-tableau) que vous souhaitez comparer dans un champ séparé et utiliser l'argument meta_compare pour filtrer.

0
Rarst