web-dev-qa-db-fra.com

URL personnalisée allant à 404

J'ai eu quelque chose qui fonctionne vraiment bien - une page de recherche avec une URL personnalisée. Cela fonctionne bien sauf lorsque j'ajoute la page 404.php à mon thème. Puis la page 404s. Et si je l'enlève, ça recommence à fonctionner.

Existe-t-il un moyen de rechercher un 404 pour cette URL et de "l'annuler"? J'ai essayé, en quelque sorte, en vérifiant $GLOBALS['wp_query']->is_404 = false; mais cela n'a pas fonctionné. Puis-je placer mes fonctions dans une action qui s'exécute avant le contrôle 404? J'ai essayé de créer un article avec cette limace, mais cela m'amène évidemment à cette page, pas à ma page personnalisée.

Voici le code avec lequel j'ai créé l'URL personnalisée:

add_action( 'parse_request', 'allow_blank_search');
function allow_blank_search(){
  $path = $_SERVER['REQUEST_URI'];
  if(substr($path, 0, 16) == '/catalog-of-work'){
    $_GET['s'] = '';
    $GLOBALS['wp_query']->is_search = true;
  }
  $GLOBALS['wp_rewrite']->search_base = 'catalog-of-work';  
}

function search_url_rewrite_rule() {
    if (!empty($_GET['s'])) {
        wp_redirect(home_url("/catalog-of-work/") . urlencode(get_query_var('s')));
        exit();
    }   
}
add_action('parse_request', 'search_url_rewrite_rule');
1
dgig

Rediriger tôt

Tout d’abord, votre fonction de redirection doit être connectée tôt: vous ne vous fiez pas aux variables de requête, vous pouvez donc utiliser init hook:

function search_redirect() {
    if (!empty($_GET['s'])) {
       $home = trailingslashit(home_url('catalog-of-work'));
       wp_safe_redirect($home.urlencode(get_query_var('s')));
       exit();
    }   
}

add_action('init', 'search_redirect');

La raison en est que cela redirigera la demande beaucoup plus tôt, ce qui économisera beaucoup de traitement.

Définir les variables de requête correctement

Désormais, vous devez indiquer à WordPress que, lorsque l'URL /catalog-of-work est visitée, il doit prendre en compte une demande de recherche.

function custom_search_query_var($do, $wp) {
    $path = trim(parse_url(esc_url_raw(add_query_arg([])), PHP_URL_PATH), '/');
    $home_path = trim(parse_url(esc_url_raw(home_url()), PHP_URL_PATH), '/');
    $home_path and $path = trim(substr($path, strlen($home_path)), '/');
    if (strpos($path, 'catalog-of-work') === 0) {
        $wp->query_vars['s'] = trim(substr($path, 15), '/');
        $do = false;
    }

    return $do;
}

add_action('do_parse_request', 'custom_search_query_var', 10, 2);

Il y a quelques points à noter dans le code ci-dessus:

  • J'ai utilisé do_parse_request hook au lieu de parse_request. Cela me permet d’empêcher complètement l’analyse de règles d’analyse de WordPress lorsque l’URL /catalog-of-work est visité. Le traitement des vars de requête pouvant être un processus lent, cela pourrait améliorer les performances de votre page.
  • Ma logique pour déterminer l'URL actuelle utilise add_query_arg au lieu de diriger l'accès à $_SERVER. C'est mieux parce que la fonction prend en charge certains cas Edge.
  • Ma logique gère le cas où votre URL personnelle est quelque chose comme example.com/wp au lieu de example.com. Comme l'URL de la maison peut facilement être modifiée, la fonction est ainsi plus stable et fonctionnera dans différentes situations.
  • Le code que j'ai utilisé définit la variable "s" dans le tableau $wp->query_vars. $wp est l'instance actuelle de WP class transmise par le hook do_parse_request. C'est mieux pour deux raisons:
    1. vous évitez d'accéder directement aux variables globales
    2. définir des variables sur global $wp_query n'est pas fiable sur do_parse_request (ni sur parse_request que vous avez utilisé) car ces points d'ancrage se produisent avant que $wp_query ne soit traité et qu'une réinitialisation puisse encore s'y produire, supprimant la requête s. En définissant la requête var sur $wp objet, il veillera à transmettre les variables à $wp_query.

Prévenir 404

Faire des choses comme je l'ai décrit, avoir un modèle 404 n'affecte en rien, car WordPress ne fait pas définit le statut 404 pour les requêtes de recherche.

Cependant, mon code (tout comme votre code, du moins le code que vous avez posté) n'agit pas sur le modèle, donc, par défaut, WordPress chargera search.php.

Il est très possible que votre modèle search.php (ou le modèle que vous utilisez) vérifie la présence de have_posts() et charge le modèle 404 (s'il est trouvé) lorsqu'il n'y a aucune publication.

Cela dépend vraiment du thème que vous utilisez.

Par exemple, le thème Twentyfifteen contient quelque chose comme:

<?php if ( have_posts() ) : ?>
    // ... redacted loop code here...    
else :
    // If no content, include the "No posts found" template.
    get_template_part( 'content', 'none' );
endif;
?>

Si votre thème contient quelque chose comme ceci, le modèle 404 peut être chargé lorsqu'il n'y a aucune publication, ce qui se produit lorsque la requête de recherche est vide.

Si tel est le problème, vous devez modifier votre modèle de recherche (ou si le thème est une tierce partie ou un thème principal, vous devez créer un thème child ) pour que le modèle de recherche traite le cas de non-publication en fonction de vos besoins. .

1
gmazzap

Je pense que vous cherchez une solution dans la mauvaise direction. Au lieu d'essayer d'empêcher une recherche avec zéro résultat de finir au gabarit 404, j'essaierais de l'attraper ici. En d'autres termes, dans votre modèle 404, incluez un test si la recherche a échoué et si oui, redirigez. Comme ça:

if (!empty($_GET['s']))
  { search_url_rewrite_rule();}
else
  { normal 404 }
0
cjbj