web-dev-qa-db-fra.com

Comment arrêter wordpress pour faire la requête par défaut?

Mon objectif est une redirection vers un modèle personnalisé basé sur une nouvelle règle de réécriture, mais sans avoir à utiliser wordpress pour effectuer des requêtes inutiles.

mon code:

function add_rewrite_rules() {

    add_rewrite_rule(
        '^settore/([^/]*)/?$',
        'index.php?settore=$matches[1]',
        'top'
    );

  add_rewrite_tag('%settore%','(caldareria|tessile)');
}
add_action( 'init', 'add_rewrite_rules' );

function set_root_category_template($template){
    $settore = get_query_var('settore');
    if($settore != '') $template = locate_template('root-taxonomy.php');
    return $template;
}
add_filter('template_include','set_root_category_template',99);

La redirection est juste comme il faut, mais si je vérifie $ wp_query-> posts dans root-taxonomy.php, je vois une liste de publications régulières. Au lieu de cela, dans cette page, je ferai une requête personnalisée demandant des données de termes de taxonomie spécifiques et, par conséquent, la requête par défaut est totalement inutile. Comment puis-je l'arrêter? Après tout, je ne passe aucune requête par défaut à index.php. Je ne comprends donc pas pourquoi wp continue à faire une requête.

4
Luca Reghellin

Arrêter WordPress pour exécuter la requête principale est difficile: vous devez creuser au cœur de WordPress.

Flux de travail frontal WordPress:

  1. wp-blog-header.php appelle la fonction wp()
  2. wp() function crée une instance de wp class , et appelle la méthode main() sur celle-ci.
  3. main() code de la méthode:

    public function main($query_args = '') {
      $this->init();
      $this->parse_request($query_args); // build query vars starting from url
      $this->send_headers();
      $this->query_posts();  // run main query via WP_Query using built query vars
      $this->handle_404(); // if query has no results set 404 headers and WP_Query props
      $this->register_globals();
    }
    
  4. wp-blog-header.php include template-loader.php qui charge le fichier modèle en fonction de la requête

Donc, le seul moyen d'arrêter la requête principale est d'empêcher l'exécution de wp().

Cela peut être fait avec un crochet d’aube, faites ce dont vous avez besoin, et finalement exit().

Le problème de cette approche est que si vous empêchez l'exécution de wp(), vous empêchez également la classe wp d'analyser la demande, de sorte que les éléments de réécriture que vous ajoutez ne soient pas analysés.

Par conséquent, au lieu d’ajouter une balise de réécriture et une règle de réécriture, vous pouvez regarder directement le url pour choisir s’il s’agit de celui qui doit déclencher votre action personnalisée.

Commençons par écrire une fonction qui ne renvoie que le parte relatif de l’url, par ex. Si l'URL actuelle est quelque chose comme example.com/wp/path/to/somewhere?foo=bar et que votre URL personnelle est example.com/wp/, la fonction renvoie path/to/somewhere:

function get_relative_url() {
  $home_path = rtrim( parse_url( home_url(), PHP_URL_PATH ), '/' );
  $path = trim( substr( add_query_arg( array() ), strlen( $home_path ) ), '/' );
  $qs = array_keys( $_GET );
  if ( ! empty( $qs ) ) {
    $path = remove_query_arg( $qs, $path );
  }
  return $path;
}

Maintenant, nous pouvons utiliser un point d'ancrage précoce pour examiner l'URL, et ce n'est que si elle contient le chemin souhaité que nous allons définir la variable $settore, charger le modèle et quitter:

add_action( 'wp_loaded', function() { // 'wp_loaded' hook happen before wp() is ran

  $path = get_relative_url();
  $url_parts = explode( '/', $path );
  if (
    isset( $url_parts[1] )
    && $url_parts[0] === 'settore'
    && in_array( $url_parts[1], array( 'caldareria', 'tessile' ), TRUE )
  ) {
    // ok the current url is something like example.com/settore/tessile
    // and 'tessile' is in the variable $url_parts[1]
    $template = locate_template( 'root-taxonomy.php' );
    if ( empty( $template ) ) return; // do nothing if template not found
    global $settore;
    $settore = $url_parts[1]; // in the template you can access to $settore variable.
    require_once $template;
    exit(); // prevent WordPress to do anything else
  }

} );

C'est tout.

Dans le code ci-dessus, il était facile de comprendre si l'URL actuelle était droite, et de définir la variable $settore, car la structure de l'URL était simple. Pour les structures plus complexes, vous avez probablement besoin d'une correspondance rationnelle un outil comme composant de routage Symfony pour faire correspondre l’url à certaines variables.

Cette approche est celle que j’ai utilisée dans Cortex , jetez-y un coup d’œil si vous avez l’intention de faire ce genre de chose.

Gotchas

comme vous pouvez le constater, la requête principale (global $wp_query) dans le code que j'ai posté n'est pas utilisée. Dans votre modèle, il s'agira d'un objet WP_Query vide. Tout élément désignera donc la requête principale, par exemple. Les balises de modèle telles que is_tax(), is_archive() ou autres ne fonctionneront pas.

Cela s'appliquera également à l'en-tête et au pied de page, car vous utiliserez très probablement get_header() et get_footer() dans votre 'root-taxonomy.php'.

De plus, certains plugins peuvent ne pas fonctionner correctement, par exemple Si vous utilisez un plugin SEO qui définit une balise de titre en fonction de la requête, il y aura des problèmes.

Une solution possible consiste à définir manuellement les propriétés de la requête principale donnant accès à global $wp_query ou à utiliser un en-tête personnalisé, par exemple. get_header('root-tax'), pour votre modèle personnalisé et gérer header-root-tax.php balise de titre personnalisée et/ou tout autre problème.

4
gmazzap

pourquoi pas comme ça?

add_action( 'pre_get_posts', 'my_post_queries' );
function my_post_queries( $query ) {
    if ($query->is_main_query() && !is_admin()) {
        // maybe check for specific page here
        // if (is_tax('your-taxonomy') { 
        $query = false;
        remove_all_actions ( '__after_loop');
        // }
    }
}

Ou ai-je mal compris la question?

1
Web-Entwickler