web-dev-qa-db-fra.com

Rediriger les archives de blogs dans un certain format

Les URL de mon blog étaient les suivantes:

http://example.com/2014/03

J'ai changé le permalien de mon site de /%postname%/ à /%postid%/%postname%/, et à l'aide du plug-in Redirection, j'ai défini une redirection comme: redirection 1

et ça marche. Mais le problème se produit dans les URL des archives. La nouvelle URL d'archive générée avec un/date/nom de base avant les dates, comme:

http://example.com/date/2014/03

J'essaie d'utiliser le même plugin de redirection pour rediriger l'URL, mais j'ai échoué: redirection 2

J'ai ensuite essayé d'écrire moi-même .htaccess (sans expérience d'écriture .htaccess) avec:

Redirect permanent http://example.com/([0-9]+)/([0-9]+) http://example.com/date/([0-9]+)/([0-9]+)

avec l'aide de éditeur htaccess et de ce blog . Mais échoué aussi.

Comment puis-je laisser mon blog ne pas obtenir 404 sur une telle URL d'archive? J'ai bien peur que je ne sois pas bête avec la règle de réécriture jusqu'à maintenant. :(

1
Mayeenul Islam

Je travaille sur un plugin qui gère des choses comme ça. Pendant son développement, je souhaite partager un code dérivé de mon plugin qui puisse vous aider, j'espère.

Si vous regardez vos urls sources , elles sont faciles à reconnaître: vous avez 2 cas dans lesquels vous devez rediriger des personnes:

  1. l'url contient 2 morceaux et les deux sont numériques, premier de 4 chiffres, le second est compris entre 1 et 12
  2. l'url contient une seule pièce et c'est un message valide

Regarder le nombre de pièces est très facile, est une question de count() et de explode(), en regardant les post-slug valides doivent être interrogés dans la base de données.

Flux de travail

  1. Obtenez l'URL
  2. Eclatez les morceaux d'url et comptez-les: si comptez pas 1 ou 2, ne faites rien
  3. Vérifier les morceaux d'URL et appliquer une redirection si nécessaire:
    • si le nombre est égal à 1, vérifiez s'il s'agit d'une publication valide et, le cas échéant, d'une redirection
    • si le nombre est égal à 2, vérifiez si les éléments ressemblent à /%year%/%monthnum% et, le cas échéant, à une redirection

Les performances du numéro 3 peuvent être améliorées en utilisant un cache basé sur les transitoires.

1. Obtenez l'URL

Ecrivons une fonction qui récupère les morceaux d’URL. Il doit retirer la partie home_url() des URL.

function get_url_pieces() {
  $home_path = trim( parse_url( home_url(), PHP_URL_PATH ), '/' );
  $full = trim( str_replace( $home_path, '', add_query_arg( array() ) ), '/' );
  $sane_array = explode( '?', $full );
  // removing any query string
  $qs = array();
  if ( isset( $sane_array[ 1 ] ) ) parse_str( $sane_array[ 1 ], $qs );
  $stripped = trim( $sane_array[ 0 ], '/\\' );
  $pieces = ! empty( $stripped ) ? array_filter( explode( '/', $stripped ) ) : array();
  return $pieces;
}

2. Eclatez les morceaux d’URL et comptez-les: si comptez pas 1 ou 2, ne faites rien

Cette partie du flux de travail doit être exécutée aussi facilement que possible. 'after_setup_theme' est un bon endroit car il est disponible à la fois pour les plugins et les URL et est assez tôt.

add_action( 'after_setup_theme', function() {
  if ( is_admin() ) return;
  $url_pieces = get_url_pieces();
  if ( is_array($url_pieces) ) {
    if ( count( $url_pieces ) === 1 ) {
      my_post_redirect( $url_pieces );
    } elseif ( in_array( count($url_pieces), array(2, 3), TRUE ) ) {
      my_date_redirect( $url_pieces );
    }
  }
} );

3. Vérifier les morceaux d'URL et appliquer une redirection si nécessaire

Première fonction pour les urls 2 pièces

function my_date_redirect( Array $pieces ) {
  $cached = redirect_if_cached( $pieces );
  // if we are here url is not cached, see redirect_if_cached() below
  // let's check date format
  if ( ! in_array( count($pieces), array( 2, 3), TRUE ) ) return;
  if ( ! strlen("{$pieces[0]}") === 4 ) return;
  $day = ! isset( $pieces[2] ) ? '01' : $pieces[2];
  if ( ! checkdate ( (int)$pieces[1], (int) $day, (int) $pieces[0] ) ) return;
  // that's a valid date
  // cache and redirect
  $redirect = "date/{$pieces[0]}/{$pieces[1]}";
  if ( isset($pieces[2]) ) $redirect .= "/{$pieces[2]}";
  $cached[ serialize($pieces) ] = $redirect;
  set_transient('my_redirects', $cached);
  wp_safe_redirect( home_url( $redirect ), 301 );
  exit();
}

Deuxième fonction pour les urls 1 pièces

function my_post_redirect( Array $pieces ) {
  $cached = redirect_if_cached( $pieces );
  // if we are here url is not cached, see redirect_if_cached() below
  if ( ! count( $pieces ) === 1 ) return;
  global $wpdb;
  $query =  "SELECT ID, post_name FROM {$wpdb->posts} WHERE (post_status = 'publish'";
  $query .= ( is_user_logged_in() ) ? " OR post_status = 'private')" : ')';
  $query .= " AND post_type = 'post' AND post_name = %s";
  $post = $wpdb->get_row( $wpdb->prepare( $query, $pieces[0] ) );
  if ( empty($post) ) return;
  // that's a valid slug
  // cache and redirect
  $redirect = "{$post->ID}/{$pieces[0]}";
  $cached[ serialize( $pieces ) ] = $redirect;
  set_transient( 'my_redirects', $cached );
  wp_safe_redirect( home_url( $redirect ), 301 );
  exit();
}

Mise en place du cache

function redirect_if_cached ( Array $pieces ) {
  $cached = array_filter( (array) get_transient('my_redirects') );
  $key = serialize( $pieces );
  if ( array_key_exists( $key, $cached ) ) {
    wp_safe_redirect( home_url( $cached[$key] ), 301 );
    exit();
  }
  // if url is not cached return what's currently cached
  return $cached;
}
2
gmazzap