J'ai la requête suivante que j'appelle dans mon modèle taxonomy.php via query_brands_geo('dealers', 'publish', '1', $taxtype, $geo, $brands);
Cette fonction fonctionne parfaitement. Toutefois, après avoir lu le codex pour les publications de requête, il a mentionné pré_get_posts comme moyen privilégié de modification de la requête par défaut. Les pre_get_posts seraient-ils plus efficaces que ma fonction wp_query ci-dessous?
Si tel est le cas, comment pourrais-je construire le pre_get_posts et transmettre ma variable et ma requête ci-dessous?
function my_custom_query($posttype, $poststatus, $paidvalue, $taxtype, $geo, $brands) {
global $wp_query;
$wp_query = new WP_Query();
$args = array(
'post_type' => $posttype,
'post_status' => array($poststatus),
'orderby' => 'Rand',
'posts_per_page' => 30,
'meta_query' => array(
array(
'key' => 'wpcf-paid',
'value' => array($paidvalue),
'compare' => 'IN',
)
),
'tax_query' => array(
'relation' => 'AND',
array(
'taxonomy' => $taxtype,
'field' => 'slug',
'terms' => $geo
),
array(
'taxonomy' => 'brands',
'field' => 'slug',
'terms' => $brands
)
)
);
return $wp_query->query($args);
}
pre_get_posts
exécutera la même requête, donc les deux prendront le même temps. Toutefois, si vous utilisez l'action pre_get_posts
, vous enregistrez une ou plusieurs requêtes SQL. À l'heure actuelle, WordPress exécute la requête par défaut, puis vous exécutez votre requête avec cette fonction qui remplace les résultats de la requête par défaut (la requête par défaut résultante est donc inutile). Vous trouverez ci-dessous comment déplacer votre $args
vers
function custom_pre_get_posts($query, $posttype='dealers', $poststatus='publish', $paidvalue='1', $taxtype='any_default_value', $geo='any_default_value', $brands='any_default_value') {
// filter your request here.
if($query->is_category) {
$args = array(
'post_type' => $posttype,
'post_status' => array($poststatus),
'orderby' => 'Rand',
'posts_per_page' => 30,
'meta_query' => array(
array(
'key' => 'wpcf-paid',
'value' => array($paidvalue),
'compare' => 'IN',
)
),
'tax_query' => array(
'relation' => 'AND',
array(
'taxonomy' => $taxtype,
'field' => 'slug',
'terms' => $geo
),
array(
'taxonomy' => 'brands',
'field' => 'slug',
'terms' => $brands
)
)
);
$query->query_vars = $args;
}
}
add_action('pre_get_posts', 'custom_pre_get_posts');
Une réponse tardive car la réponse la plus votée cassera votre requête et n'est tout simplement pas vraie sur certains points principaux.
Tout d’abord, WordPress utilise en interne query_posts()
(un fin emballage autour de WP_Query
que ne devrait pas être utilisé dans des thèmes ou des plugins) pour créer un WP_Query
. Ce WP_Query
agit en tant que boucle/requête principale. Cette requête passera par de nombreux filtres et actions jusqu'à ce que la chaîne de requête SQL réelle soit générée. L'un d'entre eux est pre_get_posts
. Les autres sont posts_clauses
, posts_where
, etc. qui aussi vous permettent d'intercepter le processus de création d'une chaîne de requête.
Un regard en profondeur sur ce qui se passe à l'intérieur du noyau
WordPress exécute la fonction
wp()
(danswp-includes/functions.php
), qui appelle$wp->main()
($wp
est un objet de la classe WP, définie danswp-includes/class-wp.php
). Ceci dit à WordPress de:
- Analyser l'URL dans une spécification de requête en utilisant
WP->parse_request()
- pour plus d'informations, voir ci-dessous.- Définissez toutes les variables is_ utilisées par les balises conditionnelles à l'aide de
$wp_query->parse_query()
($wp_query
est un objet declass WP_Query
, défini danswp-includes/query.php
). Notez que malgré le nom de cette fonction, dans ce cas,WP_Query->parse_query
ne fait en réalité aucune analyse syntaxique pour nous, puisque ceci est fait avant parWP->parse_request()
.- Convertissez la spécification de requête en requête de base de données MySQL et exécutez la requête de base de données pour obtenir la liste des publications, dans la fonction WP_Query-> get_posts (). Enregistrez les articles dans l'objet $ wp_query à utiliser dans la boucle WordPress.
Source Codex
Si vous voulez vraiment modifier la requête principale, vous pouvez utiliser une grande variété de filtres. Utilisez simplement $query->set( 'some_key', 'some_value' );
pour changer les données ou utilisez $query->get( 'some_key' );
pour récupérer les données pour effectuer des contrôles conditionnels. Cela vous évitera de faire une seconde requête, car vous modifiez la requête SQL uniquement.
Si vous devez faire une requête additional, utilisez un objet WP_Query
. Cela va ajouter une autre requête à la base de données.
Comme les réponses fonctionnent toujours mieux avec un exemple, vous en avez ici un très gentil (accessoire de Brad Touesnard), qui étend simplement l’objet principal et est donc assez réutilisable (en faire un plugin):
class My_Book_Query extends WP_Query
{
function __construct( $args = array() )
{
// Forced/default args
$args = array_merge( $args, array(
'posts_per_page' => -1
) );
add_filter( 'posts_fields', array( $this, 'posts_fields' ) );
parent::__construct( $args );
}
public function posts_fields( $sql )
{
return "{$sql}, {$GLOBALS['wpdb']->terms}.name AS 'book_category'";
}
}
Vous pouvez ensuite exécuter votre seconde _/requête supplémentaire, comme vous pouvez le voir dans l'exemple suivant. N'oubliez pas de réinitialiser votre requête par la suite.
$book_query = new My_Book_Query();
if ( $book_query->have_posts() )
{
while ( $book_query->have_posts() )
{
$book_query->the_post();
# ...do stuff...
} // endwhile;
wp_reset_postdata();
} // endif;
Consultez les réponses sous Quand utiliser WP_query (), query_posts () et pre_get_posts .
C'est une excellente ressource si vous avez des doutes.