remplace la classe WP_Query dans la requête principale

4

Pour un projet, je devais modifier considérablement le comportement de WP_Query. Donc, ce que je faisais était d'étendre WP_Query comme suit:

class eacf_shared_query extends \WP_Query {

    function query( $query ) {

        // do things before ...

        $posts = parent::query($query);

        // do things after ...

        return $posts;
    }

Cela fonctionne comme un charme pour toutes mes requêtes personnalisées pour lesquelles j'utilise maintenant ma classe étendue, mais je ne parviens pas à trouver le moyen de l'intégrer à la requête principale.

Donc ma question est la suivante: Existe-t-il un moyen connu de remplacer / étendre la classe WP_Query dans la requête principale?

J'ai trouvé que ce qui précède était la seule solution et je ne suis pas allé plus loin en utilisant les filtres fournis dans la classe d'origine:

  • Il semble qu'aucune paire de filtres ne soit garantie d'être exécutée avant et après la requête, je ne peux donc pas réaliser une construction comme dans l'exemple ci-dessus.
  • La logique
  • Ma action "après" contient des appels imbriqués à WP_Query () qui aboutissent trop facilement dans une boucle de requête si j'utilise des filtres.
  • Les filtres SQL ne semblent pas assez puissants pour créer une requête unique récupérant toutes les publications (comme la construction d’une requête UNION). J'ai besoin de fusionner des posts de différents blogs en une seule requête et il semble que cela ne soit pas possible avec des filtres comme posts_clauses_request ou query .
posée s1lv3r 16.10.2013 - 13:45

2 réponses

4

Ok, donc c'est faisable mais pourrait éventuellement gâcher un certain nombre de choses sur la ligne, donc c'est à vos risques et périls, mais il en va de même de tout:)

J'essayais de le faire pour utiliser une classe d'extension GeoQuery afin de classer les événements en fonction de leur distance.

La façon la plus simple de le faire est la suivante:

add_action( 'after_setup_theme', 'alt_query_class', 1, 0 );
function alt_query_class() {
    if ( ! is_admin() && $GLOBALS[ 'wp_query' ] instanceof WP_Query ) {
         $GLOBALS[ 'wp_the_query' ] = new WP_Query_Extended();
         $GLOBALS[ 'wp_query' ] = $GLOBALS[ 'wp_the_query' ];
    }
}

Dans votre classe de requête étendue, vous ne feriez que ce que vous avez décrit ci-dessus, mais si les fonctionnalités ajoutées ne sont pas souhaitables pour chaque requête exécutée, vous devez effectuer une logique d'installation / de démontage, car nous remplaçons chaque instance de WP_Query avec le nouveau.

Dans mon cas, j’ai utilisé le filtre pre_get_posts avec une priorité tardive pour vérifier si je devais ajouter mes fonctionnalités ou non une fois toutes les manipulations de la requête effectuées.

class WP_Query_Extended extends WP_Query {

    function query( $args = array() ) {

        // setup functions
        add_filter( 'pre_get_posts', array( $this, 'check_setup_needed' ), 1000 );

        // run the query
        parent::query( $args );

        // tear down functions
        $this->teardown();
    }

    function check_setup_needed( $query ) {

        // test setup criteria
        if ( $query->get( 'somevar' ) ) {
            $this->setup();
        }

        return $query;
    }

    function setup() {
        // add any filters etc... here
    }

    function teardown() {
        // remove filters etc... here
        remove_filter( 'pre_get_posts', array( $this, 'check_setup_needed' ) );
    }

}

UPDATE:

Cela pose un gros problème: si quelqu'un utilise query_posts() , par exemple. Cela pourrait être dans un plugin ou si vous écrivez un plugin, alors peut-être un thème puis cette fonction réinitialisera le $wp_query global en une instance WP_Query et il n'y aura pas de filtre pour le changer ultérieurement.

Si vous devez réellement faire un query_posts() (vous ne devriez pas!), vous pouvez faire $wp_query->query( $args ) à la place.

    
réponse donnée sanchothefat 29.01.2014 - 14:39
1

Je vous suggèrerais d'ajouter un filtre au crochet posts_results pour remplacer $ posts par le résultat de votre requête personnalisée. Cependant, cette méthode produit un traitement redondant lorsque la requête principale est traitée en premier, puis les résultats sont "écrasés" par vos résultats personnalisés.

    
réponse donnée Dominic Yun 30.10.2013 - 14:13

Lire d'autres questions sur les étiquettes