web-dev-qa-db-fra.com

Est-il possible de commander plusieurs fois quand on utilise ce meta_value_num?

En lisant la documentation order & orderby , il n’est pas clair pour moi si la prise en charge de la commande est basée sur plusieurs valeurs meta_key.

Évidemment, en utilisant meta_query, je peux renvoyer des publications en fonction de plusieurs paires clé-valeur, mais je veux pouvoir contrôler l'ordre dans lequel ces résultats sont renvoyés en fonction de plusieurs meta_keys.

Par exemple, j'ai des pages qui ont plusieurs catégories et chaque catégorie a un rang numérique. Si un utilisateur recherche des pages appartenant à l'une des trois catégories différentes, je peux renvoyer tous les articles nécessaires avec les éléments suivants:

$query = array(
  'order' => 'DESC',
  'orderby' => 'meta_value_num',
  'meta_query' => array(
    'relation' => 'OR',
    array( 'key' => 'cat1', 'type' => 'numeric' ),
    array( 'key' => 'cat2', 'type' => 'numeric' ),
    array( 'key' => 'cat3', 'type' => 'numeric' )
  );
);

Cependant, une fois que ceux-ci sont renvoyés, j'aimerais qu'ils soient ordonnés en fonction de la valeur numérique la plus élevée parmi toutes les catégories pour lesquelles les résultats ont été renvoyés. En d'autres termes, les publications avec une valeur 9 dans cat1 apparaissent dans le même ordre que les publications avec une valeur 9 dans cat3.

En regardant cette réponse , il semble qu'un meta_key ne soit même pas nécessaire pour 'orderby' => 'meta_value_num', mais cela ne correspond pas à la documentation de meta_value, qui est bien plus documenté que meta_value_num... Toute clarification serait utile. Merci!

4
Dan

Vous voudrez peut-être vérifier les améliorations de la requête dans WP 4.2 pour "orderby" et "meta_query". Les détails sont sur https://make.wordpress.org/core/2015/03/30/query-improvements-in-wp-4-2-orderby-and-meta_query .

Essayez de nommer vos clauses meta_query, puis commandez-les.

Le code suivant n'est pas testé:

$query = array(
  'order' => 'DESC',
  'meta_query' => array(
    'relation' => 'OR',
    'cat1-clause' => array( 'key' => 'cat1', 'type' => 'numeric' ),
    'cat2-clause' => array( 'key' => 'cat2', 'type' => 'numeric' ),
    'cat3-clause' => array( 'key' => 'cat3', 'type' => 'numeric' )
  );
  'orderby' => array(
    'cat1-clause' => 'ASC',
    'cat2-clause' => 'ASC',
    'cat3-clause' => 'ASC',
  ),
);
1
Pim Schaaf

Si vous examinez la méthode get_posts de WP_Query, il est facile de déboguer SQL en générant la variable transmise au filtre posts_request.

// Debug the WP_Query sql
add_filter( 'posts_request', function( $sql ) {
  echo "<pre>";
  var_dump( $sql );
  echo "</pre>";
  return $sql;
} );

Le résultat devrait ressembler à ceci:

string(426) "SELECT SQL_CALC_FOUND_ROWS  wp_posts.* FROM wp_posts  INNER JOIN wp_postmeta ON ( wp_posts.ID = wp_postmeta.post_id ) WHERE 1=1  AND wp_posts.post_type = 'post' AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private') AND (
  wp_postmeta.meta_key = 'cat1'
  OR
  wp_postmeta.meta_key = 'cat2'
  OR
  wp_postmeta.meta_key = 'cat3'
) GROUP BY wp_posts.ID ORDER BY wp_postmeta.meta_value+0 DESC LIMIT 0, 10"

La requête peut sembler correcte au début, mais ce n’est pas le cas. Il utilise le meta_value de la première ligne de la jointure interne pour la clause ORDER BY. Dans ce cas, c'est 'cat1'. Pour changer ce comportement, nous pouvons utiliser le hook posts_orderby pour modifier l'instruction ORDER BY et utiliser la fonction MAX mysql afin qu'il utilise la valeur la plus élevée de toutes les valeurs méta au lieu de la première ligne.

// Filter to alter the orderby sql
function nvdGMCWh_alter_posts_orderby( $sql ) {
  return "MAX( $wpdb->postmeta.meta_value+0 ) DESC";
} // - alter_posts_orderby
// Register the filter
add_filter( 'posts_orderby', 'nvdGMCWh_alter_posts_orderby' );

// The WP_Query
$res = new WP_Query;
$args = [
  'order' => 'DESC',
  'orderby' => 'meta_value_num',
  'meta_query' => [
    'relation' => 'OR',
    ['key' => 'cat1', 'type' => 'numeric'],
    ['key' => 'cat2', 'type' => 'numeric'],
    ['key' => 'cat3', 'type' => 'numeric'],
  ],
]; // - $args
// Execute the query and get the results
$result = $res->query( $args );
// Clean up the filter so it won't affect later queries
remove_filter( 'posts_orderby', 'nvdGMCWh_alter_posts_orderby' );
// Loop through the results
foreach ( $result as $post ) {
  // ... code here
} // - foreach
0
forsvunnet