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:
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é:
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. :(
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:
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.
/%year%/%monthnum%
et, le cas échéant, à une redirectionLes performances du numéro 3 peuvent être améliorées en utilisant un cache basé sur les transitoires.
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;
}
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 );
}
}
} );
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;
}