Je construis la fonctionnalité de tri pour un type d'article personnalisé et j'ai une méta valeur personnalisée pour les articles "En vedette". Cette valeur est définie lorsque vous cochez la case, sinon elle n'est pas définie.
L'utilisation de la valeur par défaut orderby=meta_value
avec meta_key=featured
fait en sorte que l'écran affiche uniquement les publications ayant la clé méta. S'ils ne le font pas, ils n'apparaissent même pas.
Je le veux donc si ce n'est pas réglé, ils apparaissent, mais ils apparaissent en dernier. Je suppose que je dois utiliser meta_query
à la place, mais cela ne fonctionne pas non plus.
Comment puis-je autoriser les clés méta vides, fausses ou non existantes dans les arguments WP_Query?
Mon code est ci-dessous. C'est pour trier les colonnes dans le tableau de bord, donc il modifie les arguments par défaut WP Query.
function featured_sortable_order( $vars ) {
if ( isset($vars['orderby']) && $vars['orderby'] == 'featured' ) {
$vars = array_merge( $vars, array(
'meta_key' => 'featured',
'orderby' => 'meta_value',
'order' => isset($vars['order']) ? $vars['order'] : 'asc',
) );
}
return $vars;
}
add_filter( 'request', 'featured_sortable_order' );
Le problème est que pour commander une méta-valeur, WordPress doit 'meta_key'
dans la requête est défini sur quelque chose. Mais si vous définissez 'meta_key'
sur quelque chose, WordPress ajoutera quelque chose comme:
AND ( wp_postmeta.meta_key = 'the_meta_key' )
à WHERE
clause SQL; et quelque chose comme
INNER JOIN wp_postmeta ON ( wp_posts.ID = wp_postmeta.post_id )
aux clauses join
. Donc, requête renvoie uniquement les publications contenant cette méta requête.
Une fois que vous travaillez sur le backend, et que vous appelez get_post_meta( $postid, 'featured', true)
pour que chaque post montre la colonne, ce n’est pas un gros problème de performance que vous appelez-le deux fois grâce au cache WordPress sur get meta function.
Donc, l’idée est d’obtenir tous les articles (sans ajouter de filtre sur la clé méta), puis de filtrer les articles en utilisant 'posts_results'
crochet et commander les articles en regardant la clé méta 'sélectionnée'.
Je retirerai le filtre juste après l'avoir utilisé.
add_filter( 'posts_results', 'order_by_featured', PHP_INT_MAX, 2 );
function order_by_featured ( $posts, $query ) {
// run only on admin, on main query and only if 'orderby' is featured
if ( is_admin() && $query->is_main_query() && $query->get('orderby') === 'featured' ) {
// run once
remove_filter( current_filter(), __FUNCTION__, PHP_INT_MAX, 2 );
$nonfeatured = array();
$featured = array();
foreach ( $posts as $post ) {
if ( get_post_meta( $post->ID, 'featured', TRUE ) ) {
$featured[] = $post;
} else {
$nonfeatured[] = $post;
}
}
$order = strtoupper( $query->get('order') ) === 'ASC' ? 'DESC' : 'ASC';
// if order is ASC put featured at top, otherwise put featured at bottm
$posts = ( $order === 'ASC' )
? array_merge( $nonfeatured, $featured )
: array_merge( $featured, $nonfeatured );
}
return $posts;
}
De plus, j'ajoute un filtre sur 'pre_get_post'
pour utiliser 'ASC'
comme ordre par défaut si aucun ordre n'est défini dans la requête:
add_action( 'pre_get_posts', function( $query ) {
// if no order is set set order to ASC
if (
is_admin() && $query->is_main_query()
&& $query->get('orderby') === 'featured'
&& $query->get('order') === ''
) {
$query->set( 'order', 'ASC' );
}
});