web-dev-qa-db-fra.com

Pourquoi les publications ne peuvent jamais avoir un numéro comme lien?

Voici quelque chose d’intéressant que j’ai remarqué aujourd’hui - il n’est pas possible de nommer un message par un numéro - quel que soit le thème que vous utilisez, et même si vous nommez un numéro long sans conflit de tag ou de nom de nom ou de catégorie, vous toujours obtenir 2015 ou 1826628 renommé 2015-2 ou 1826628-2.

Je suppose que ce n'est pas un bogue, mais je ne vois pas non plus pourquoi vous ne pouvez pas utiliser mysite.com/20 ou similaire comme permalien vers un message, alors que vous le nommez "20" et que permaliens sont définis sur après le nom.

1
NoBugs

Pourquoi des suffixes sont-ils ajoutés à (certains) post-slugs numériques?

Les publications WordPress peuvent presque toujours avoir des permaliens numériques, les exceptions étant les cas où ils pourraient entrer en conflit avec une autre publication, un flux ou une archive de date post après, ou réservés. La fonction wp_unique_post_slug() atténue ces conflits en ajoutant un suffixe.

Des conflits d'archives de dates potentiels surviennent lorsqu'un %postname% numérique remplit l'une des trois conditions suivantes:

/*
* Potential date clashes are as follows:
*
* - Any integer in the first permastruct position could be a year.
* - An integer between 1 and 12 that follows 'year' conflicts with 'monthnum'.
* - An integer between 1 and 31 that follows 'monthnum' conflicts with 'day'.
*/

Ainsi, lorsque vous utilisez /%postname%/ seul en tant que structure de lien permanent, les noms numériques résultent toujours en des slugs ajoutés, car WordPress les considère comme représentant une archive annuelle. C’est l’une des bonnes raisons d’utiliser des structures de lien permanent plus robustes.

Vous pourriez argumenter que WordPress ne devrait pas avoir besoin de rendre compte des chiffres de 0 à l'année du début du blog, voire de centaines, voire de millions d'années pour le moment. Cependant, en tenant compte de tels scénarios improbables, le code ne fait aucune hypothèse concernant l'environnement ou la configuration (un utilisateur peut configurer son système comme si l'année était "1" ou publier des publications avec une date dans plusieurs milliers d'années afin de renforcer la tradition fictive ), qui est sans doute une approche plus responsable.


Solution

À partir de la version 4.3.1, le comportement de WordPress resterait inchangé si la "base" était en quelque sorte préfixée aux archives postales basées sur la date, comme on peut le faire pour les post-types personnalisés. La seule solution directe consiste donc à utiliser un élément autre que /%postname%/ pour votre structure de lien permanent (par exemple, un préfixe statique non numérique: /blog/%postname%/. Ou en ajoutant la catégorie de l'article: /%category%/%postname%/).

Alternativement, l'ajout manuel de tout caractère non numérique et convivial aux URL dans le slug de chaque publication empêchera l'ajout d'un suffixe.


Hacks/Work-Arounds possibles

Toutes les autres solutions ont quelque chose de "hacky" dans le sens où elles ne s'appuient plus sur les comportements fondamentaux de WordPress pour résoudre le problème, mais tentent plutôt de les contourner en appliquant des outils de manière inhabituelle et souvent compliquée.

Par exemple, vous pouvez éventuellement utiliser un filtre 'wp_unique_post_slug' pour ignorer les conflits improbables:

// Make some "reasonable" assumptions about the dates of this blog's content.
// These assume standard date & time settings for the Host.
define( 'REASONABLE_YEAR_ARCHIVE_LOWER', 2003 );  // Unlikely that this blog published content before WP's initial release.
define( 'REASONABLE_YEAR_ARCHIVE_UPPER', 3000 );  // Probably won't publish content after/with the year 3000.

add_filter( 'wp_unique_post_slug', 'wpse_210487_reasonably_unique_post_slug', 10, 6 );

/**
 * If WordPress modified a post-slug to avoid conflicts with date archives when
 * %postname% is the first permastruct, undo the modification if the slug is an
 * "unreasonable" year. NOTE: this is a hack, and has a high potential for
 * introducing new bugs, particularly after the year
 * REASONABLE_YEAR_ARCHIVE_UPPER.
 */
function wpse_210487_reasonably_unique_post_slug( $slug, $post_ID, $post_status, $post_type, $post_parent, $original_slug ) {
  global $wpdb, $wp_rewrite;

  $permastructs   = array_values( array_filter( explode( '/', get_option( 'permalink_structure' ) ) ) );

  // Don't re-process the slug if:
  if( 'post' !== $post_type                              // - the item is not a 'post'
    || $original_slug === $slug                          // - the item's slug was not altered to resolve a conflict
    || 0 !== array_search( '%postname%', $permastructs ) // - the permalink structure does not start with %postname%
    || ! preg_match( '/^[0-9]+$/', $slug )               // - the slug is not strictly numeric
    )
    return $slug;

  // If the original slug conflicted with another post, use the WordPress-altered slug
  $check_sql       = "SELECT post_name FROM $wpdb->posts WHERE post_name = %s AND post_type = %s AND ID != %d LIMIT 1";
  $post_name_check = $wpdb->get_var( $wpdb->prepare( $check_sql, $original_slug, $post_type, $post_ID ) );
  if( $post_name_check )
    return $slug;

  // If the original slug conflicted with a feed, use the WordPress-altered slug
  if ( is_array( $wp_rewrite->feeds ) && in_array( $original_slug, $wp_rewrite->feeds ) )
    return $slug;

  // If the original slug was otherwise reserved, use the WordPress-altered slug
  if( apply_filters( 'wp_unique_post_slug_is_bad_flat_slug', false, $original_slug, $post_type ) )
    return $slug;

  // Otherwise, if the numeric slug will never reasonably conflict with a year archive, undo WordPress's slug modification
  $slug_num = intval( $original_slug );
  if( REASONABLE_YEAR_ARCHIVE_LOWER > $slug_num || REASONABLE_YEAR_ARCHIVE_UPPER < $slug_num )
    return $original_slug;

  return $slug;
}

Notez que je n'ai pas testé le code ci-dessus et décourage fortement son utilisation. Il se peut que même en appliquant le slug prévu, il soit toujours dirigé vers l'archive datée.

L'application de l'API Rewrite peut également permettre de trouver d'autres solutions (probablement aussi hacky).

2
bosco