web-dev-qa-db-fra.com

Supprimer le slug des URL de publication de type publication personnalisé

Il semble que toutes les ressources Web basées sur le sujet de la suppression d’un slug de type message personnalisé, c’est-à-dire

yourdomain.com/CPT-SLUG/post-name 

sont maintenant des solutions très obsolètes faisant souvent référence aux installations antérieures à la version 3.5 WP. Une commune est de:

'rewrite'   => array( 'slug' => false, 'with_front' => false ),  

dans votre fonction register_post_type. Cela ne fonctionne plus et est trompeur. Je demande donc à la communauté au troisième trimestre 2018 au bord de WordPress 5 ...

Quels sont les moyens modernes et efficaces pour supprimer le slug de type de publication de l'URL d'une publication de type personnalisée à partir de l'argument de réécriture ou ailleurs?

MISE À JOUR: Il semble y avoir plusieurs façons de forcer cela à fonctionner avec regex. En particulier, la réponse de Jan Beck si vous êtes toujours disposé à surveiller la création de contenu pour vous assurer qu'aucun nom de page/publication ne soit créé en conflit ... Cependant, je suis convaincu qu'il s'agit d'une faiblesse majeure de WP, où elle devrait être traité pour nous. Les deux en tant qu'option/hook lors de la création d'un CPT ou d'un ensemble d'options avancé pour les permaliens. S'il vous plaît soutenir le billet de piste.

Note de bas de page: Merci de soutenir ce ticket de traçage en visionnant/promouvant ce billet: https://core.trac.wordpress.org/ticket/34136#ticket

43
Ben Racicot

Le code suivant fonctionnera, mais vous devez simplement garder à l’esprit que des conflits peuvent survenir facilement si le slug de votre type de message personnalisé est identique à un slug de page ou de message ...

Tout d'abord, nous allons supprimer le slug du permalien:

function na_remove_slug( $post_link, $post, $leavename ) {

    if ( 'events' != $post->post_type || 'publish' != $post->post_status ) {
        return $post_link;
    }

    $post_link = str_replace( '/' . $post->post_type . '/', '/', $post_link );

    return $post_link;
}
add_filter( 'post_type_link', 'na_remove_slug', 10, 3 );

Retirer la limace ne suffit pas. Pour le moment, vous obtiendrez une page 404 car WordPress n'attend que les publications et les pages de se comporter de cette manière. Vous devrez également ajouter les éléments suivants:

function na_parse_request( $query ) {

    if ( ! $query->is_main_query() || 2 != count( $query->query ) || ! isset( $query->query['page'] ) ) {
        return;
    }

    if ( ! empty( $query->query['name'] ) ) {
        $query->set( 'post_type', array( 'post', 'events', 'page' ) );
    }
}
add_action( 'pre_get_posts', 'na_parse_request' );

Il suffit de changer les "événements" pour votre type de message personnalisé et vous êtes prêt à partir. Vous devrez peut-être actualiser vos permaliens.

57
Nate Allen

Écrivez le code suivant dans l'enregistrement de la taxonomie.

'rewrite' => [
  'slug' => '/',
  'with_front' => false
]

La chose la plus importante à faire après le changement de code

Après avoir modifié votre document de taxonomie de type publication personnalisé, essayez d’accéder à Paramètres> Permaliens et enregistrez à nouveau vos paramètres , sans quoi la page 404 ne sera pas trouvée.

Vérifiez ici la meilleure solution: http://www.krazzycodes.com/how-to-remove-custom-post-type-taxonomy-base-from-url-in-wordpress/

19
Mayank Dudakiya

J'ai essayé de comprendre cela il n'y a pas longtemps et la réponse courte de ce que je sais est no . Pas du moins dans l'argument de réécriture.

La longue explication devient évidente si vous regardez le code actuel de register_post_type dans wp-includes/post.php ligne 1454 :

add_permastruct( $post_type, "{$args->rewrite['slug']}/%$post_type%", $permastruct_args );

Vous pouvez y voir les préfixes $args->rewrite['slug'] de la balise de réécriture %$post_type%. On pourrait penser "réglons simplement le slug sur null puis" jusqu'à ce que vous cherchiez quelques lignes:

if ( empty( $args->rewrite['slug'] ) )
    $args->rewrite['slug'] = $post_type;

Vous pouvez constater que la fonction toujours attend une valeur slug non vide et utilise le type de publication.

12
Jan Beck

En réponse à ma réponse précédente : vous pouvez bien sûr définir le paramètre rewrite sur false lors de l'enregistrement d'un nouveau type de message et gérer vous-même les règles de réécriture.

<?php
function wpsx203951_custom_init() {

    $post_type = 'event';
    $args = (object) array(
        'public'      => true,
        'label'       => 'Events',
        'rewrite'     => false, // always set this to false
        'has_archive' => true
    );
    register_post_type( $post_type, $args );

    // these are your actual rewrite arguments
    $args->rewrite = array(
        'slug' => 'calendar'
    );

    // everything what follows is from the register_post_type function
    if ( is_admin() || '' != get_option( 'permalink_structure' ) ) {

        if ( ! is_array( $args->rewrite ) )
            $args->rewrite = array();
        if ( empty( $args->rewrite['slug'] ) )
            $args->rewrite['slug'] = $post_type;
        if ( ! isset( $args->rewrite['with_front'] ) )
            $args->rewrite['with_front'] = true;
        if ( ! isset( $args->rewrite['pages'] ) )
            $args->rewrite['pages'] = true;
        if ( ! isset( $args->rewrite['feeds'] ) || ! $args->has_archive )
            $args->rewrite['feeds'] = (bool) $args->has_archive;
        if ( ! isset( $args->rewrite['ep_mask'] ) ) {
            if ( isset( $args->permalink_epmask ) )
                $args->rewrite['ep_mask'] = $args->permalink_epmask;
            else
                $args->rewrite['ep_mask'] = EP_PERMALINK;
        }

        if ( $args->hierarchical )
            add_rewrite_tag( "%$post_type%", '(.+?)', $args->query_var ? "{$args->query_var}=" : "post_type=$post_type&pagename=" );
        else
            add_rewrite_tag( "%$post_type%", '([^/]+)', $args->query_var ? "{$args->query_var}=" : "post_type=$post_type&name=" );

        if ( $args->has_archive ) {
            $archive_slug = $args->has_archive === true ? $args->rewrite['slug'] : $args->has_archive;
            if ( $args->rewrite['with_front'] )
                $archive_slug = substr( $wp_rewrite->front, 1 ) . $archive_slug;
            else
                $archive_slug = $wp_rewrite->root . $archive_slug;

            add_rewrite_rule( "{$archive_slug}/?$", "index.php?post_type=$post_type", 'top' );
            if ( $args->rewrite['feeds'] && $wp_rewrite->feeds ) {
                $feeds = '(' . trim( implode( '|', $wp_rewrite->feeds ) ) . ')';
                add_rewrite_rule( "{$archive_slug}/feed/$feeds/?$", "index.php?post_type=$post_type" . '&feed=$matches[1]', 'top' );
                add_rewrite_rule( "{$archive_slug}/$feeds/?$", "index.php?post_type=$post_type" . '&feed=$matches[1]', 'top' );
            }
            if ( $args->rewrite['pages'] )
                add_rewrite_rule( "{$archive_slug}/{$wp_rewrite->pagination_base}/([0-9]{1,})/?$", "index.php?post_type=$post_type" . '&paged=$matches[1]', 'top' );
        }

        $permastruct_args = $args->rewrite;
        $permastruct_args['feed'] = $permastruct_args['feeds'];
        add_permastruct( $post_type, "%$post_type%", $permastruct_args );
    }
}
add_action( 'init', 'wpsx203951_custom_init' );

Vous pouvez voir que l'appel add_permastruct n'inclut plus le slug. J'ai testé deux scénarios:

  1. Lorsque j'ai créé une page avec le slug "calendrier", cette page est remplacée par l'archive de type message qui utilise également le slug "calendrier".

 enter image description here 

  1. Lorsque j'ai créé une page avec le slug "my-event" et un événement (CPT) avec le slug "my-event", le type de publication personnalisé est affiché.

 enter image description here 

  1. Les autres pages ne fonctionnent pas non plus. Si vous regardez la photo ci-dessus, vous comprendrez pourquoi: la règle de type de publication personnalisée correspond toujours à un slug de page. Comme WordPress n'a aucun moyen d'identifier s'il s'agit d'une page ou d'un type de publication personnalisé qui n'existe pas, il renverra 404. C'est pourquoi vous avez besoin d'un slug pour identifier la page ou le CPT. Une solution possible serait d'intercepter l'erreur et de rechercher une page qui pourrait exister semblable à cette réponse .
7
Jan Beck

En regardant à travers les réponses ici, je pense qu'il y a place pour une meilleure solution qui combine certaines choses que j'ai apprises ci-dessus et qui ajoute la détection automatique et la prévention des doublons de post-slug.

NOTE: Assurez-vous de changer 'custom_post_type' pour votre propre nom CPT dans mon exemple ci-dessous. Il existe de nombreuses occurrences et une "recherche/remplacement" est un moyen facile de toutes les attraper. Tout ce code peut aller dans votre functions.php ou dans un plugin.

Étape 1: Désactivez les réécritures sur votre type de message personnalisé en les définissant comme "faux" lorsque vous enregistrez le message:

register_post_type( 'custom_post_type',
    array(
        'rewrite' => false
    )
);

Étape 2: Ajoutez manuellement nos réécritures personnalisées au en bas des réécritures WordPress pour notre type_post_personnalisé

function custom_post_type_rewrites() {
    add_rewrite_rule( '[^/]+/attachment/([^/]+)/?$', 'index.php?attachment=$matches[1]', 'bottom');
    add_rewrite_rule( '[^/]+/attachment/([^/]+)/trackback/?$', 'index.php?attachment=$matches[1]&tb=1', 'bottom');
    add_rewrite_rule( '[^/]+/attachment/([^/]+)/feed/(feed|rdf|rss|rss2|atom)/?$', 'index.php?attachment=$matches[1]&feed=$matches[2]', 'bottom');
    add_rewrite_rule( '[^/]+/attachment/([^/]+)/(feed|rdf|rss|rss2|atom)/?$', 'index.php?attachment=$matches[1]&feed=$matches[2]', 'bottom');
    add_rewrite_rule( '[^/]+/attachment/([^/]+)/comment-page-([0-9]{1,})/?$', 'index.php?attachment=$matches[1]&cpage=$matches[2]', 'bottom');
    add_rewrite_rule( '[^/]+/attachment/([^/]+)/embed/?$', 'index.php?attachment=$matches[1]&embed=true', 'bottom');
    add_rewrite_rule( '([^/]+)/embed/?$', 'index.php?custom_post_type=$matches[1]&embed=true', 'bottom');
    add_rewrite_rule( '([^/]+)/trackback/?$', 'index.php?custom_post_type=$matches[1]&tb=1', 'bottom');
    add_rewrite_rule( '([^/]+)/page/?([0-9]{1,})/?$', 'index.php?custom_post_type=$matches[1]&paged=$matches[2]', 'bottom');
    add_rewrite_rule( '([^/]+)/comment-page-([0-9]{1,})/?$', 'index.php?custom_post_type=$matches[1]&cpage=$matches[2]', 'bottom');
    add_rewrite_rule( '([^/]+)(?:/([0-9]+))?/?$', 'index.php?custom_post_type=$matches[1]', 'bottom');
    add_rewrite_rule( '[^/]+/([^/]+)/?$', 'index.php?attachment=$matches[1]', 'bottom');
    add_rewrite_rule( '[^/]+/([^/]+)/trackback/?$', 'index.php?attachment=$matches[1]&tb=1', 'bottom');
    add_rewrite_rule( '[^/]+/([^/]+)/feed/(feed|rdf|rss|rss2|atom)/?$', 'index.php?attachment=$matches[1]&feed=$matches[2]', 'bottom');
    add_rewrite_rule( '[^/]+/([^/]+)/(feed|rdf|rss|rss2|atom)/?$', 'index.php?attachment=$matches[1]&feed=$matches[2]', 'bottom');
    add_rewrite_rule( '[^/]+/([^/]+)/comment-page-([0-9]{1,})/?$', 'index.php?attachment=$matches[1]&cpage=$matches[2]', 'bottom');
    add_rewrite_rule( '[^/]+/([^/]+)/embed/?$', 'index.php?attachment=$matches[1]&embed=true', 'bottom');
}
add_action( 'init', 'custom_post_type_rewrites' );

REMARQUE: En fonction de vos besoins, vous voudrez peut-être modifier les réécritures ci-dessus (désactiver les rétroliens? Les flux?, Etc.). Ils représentent les types de réécriture "par défaut" qui auraient été générés si vous n’aviez pas désactivé les réécritures à l’étape 1

Étape 3: Faites à nouveau des liens permanents vers votre message personnalisé

function custom_post_type_permalinks( $post_link, $post, $leavename ) {
    if ( isset( $post->post_type ) && 'custom_post_type' == $post->post_type ) {
        $post_link = home_url( $post->post_name );
    }

    return $post_link;
}
add_filter( 'post_type_link', 'custom_post_type_permalinks', 10, 3 );

REMARQUE: vous pouvez vous arrêter ici si vous ne craignez pas que vos utilisateurs créent une publication en conflit (en double) dans un autre type de publication, ce qui créera une situation dans laquelle un seul d'entre eux peut être chargé lorsque la page est demandée.

Étape 4: Prévenir les doublons postaux

function prevent_slug_duplicates( $slug, $post_ID, $post_status, $post_type, $post_parent, $original_slug ) {
    $check_post_types = array(
        'post',
        'page',
        'custom_post_type'
    );

    if ( ! in_array( $post_type, $check_post_types ) ) {
        return $slug;
    }

    if ( 'custom_post_type' == $post_type ) {
        // Saving a custom_post_type post, check for duplicates in POST or PAGE post types
        $post_match = get_page_by_path( $slug, 'OBJECT', 'post' );
        $page_match = get_page_by_path( $slug, 'OBJECT', 'page' );

        if ( $post_match || $page_match ) {
            $slug .= '-duplicate';
        }
    } else {
        // Saving a POST or PAGE, check for duplicates in custom_post_type post type
        $custom_post_type_match = get_page_by_path( $slug, 'OBJECT', 'custom_post_type' );

        if ( $custom_post_type_match ) {
            $slug .= '-duplicate';
        }
    }

    return $slug;
}
add_filter( 'wp_unique_post_slug', 'prevent_slug_duplicates', 10, 6 );

NOTE: Ceci ajoutera la chaîne '-duplicate' à la fin de chaque slug en double. Ce code ne peut pas empêcher les doublons en double s'ils existaient déjà avant d'implémenter cette solution. Assurez-vous de vérifier les doublons en premier.

J'adorerais avoir des nouvelles de tous ceux qui donneraient une chance de voir si cela fonctionnait bien pour eux aussi.

5
Matt Keys

Vous n'avez pas besoin de tant de code dur. Il suffit d'utiliser un plugin léger:

Il a des options personnalisables.

1
T.Todua

Pour tous ceux qui lisent ceci qui ont des problèmes avec les publications pour enfants comme je l'ai fait, j'ai trouvé que le meilleur moyen était d'ajouter vos propres règles de réécriture.

Le problème principal que je rencontrais était que WordPress traitait la redirection à partir de pages profondes de 2 niveaux (messages enfants) un peu différemment par rapport aux 3 niveaux de profondeur (enfants de messages enfants).

Cela signifie que quand j'ai/post-type/post-nom/post-enfant/je peux utiliser/post-nom/post-enfant et il me redirigera vers celui avec post-type devant mais si j'ai post-type/post-name/post-child/post-petit-enfant, je ne peux pas utiliser post-name/post-child/post-petit-enfant.

En examinant les règles de réécriture, il semble que cela corresponde à des éléments autres que pagename aux premier et deuxième niveaux (je pense que le deuxième niveau correspond à l'attachement), puis fait quelque chose pour vous rediriger vers le poste approprié. À trois niveaux de profondeur, cela ne fonctionne pas.

La première chose à faire est de supprimer également le lien de type message des enfants. Cette logique devrait se produire ici si vous regardez la réponse de Nate Allen ci-dessus:

$post_link = str_replace( '/' . $post->post_type . '/', '/', $post_link );

Moi-même, j’ai utilisé un mélange de différents conditionnels pour vérifier si la publication avait des enfants, etc. afin d’obtenir le permalien qui convient. Cette partie n’est pas trop compliquée et vous trouverez des exemples de personnes qui le font ailleurs.

La prochaine étape est cependant où les choses changent de la réponse donnée. Au lieu d’ajouter des éléments à la requête principale (ce qui a fonctionné pour les publications personnalisées et leurs enfants, mais pas pour les autres enfants), j’ajoute une réécriture qui se place au bas des règles de WordPress. Ainsi, si pagename n’a pas été vérifié et qu’il était sur le point de Si vous frappez un 404, il vérifiera une dernière fois si une page du type de message personnalisé porte le même nom, sinon elle rejetterait le 404.

Voici la règle de réécriture que j'ai utilisée en supposant que "événement" est le nom de votre CPT

function rewrite_rules_for_removing_post_type_slug()
{
    add_rewrite_rule(
        '(.?.+?)?(:/([0-9]+))?/?$',
        'index.php?event=$matches[1]/$matches[2]&post_type=event',
        'bottom'
    );
}

add_action('init', 'rewrite_rules_for_removing_post_type_slug', 1, 1);

J'espère que cela aide quelqu'un d'autre, je ne pouvais rien trouver qui ait à voir avec les messages enfant ou enfant et d'éliminer la limace de ceux-ci.

0
Moe Loubani

et nous pouvons apporter quelques modifications à la fonction susmentionnée:

function na_parse_request( $query ) {

if ( ! $query->is_main_query() || 2 != count( $query->query ) || ! isset( $query->query['page'] ) ) {
    return;
}

if ( ! empty( $query->query['name'] ) ) {
    $query->set( 'post_type', array( 'post', 'events', 'page' ) );
}
}

à:

function na_parse_request( $query ) {

if ( ! $query->is_main_query() || 2 != count( $query->query ) || ! isset( $query->query['page'] ) ) {
    return;
}

if ( ! empty( $query->query['name'] ) ) {

    global $wpdb;
    $pt = $wpdb->get_var(
        "SELECT post_type FROM `{$wpdb->posts}` " .
        "WHERE post_name = '{$query->query['name']}'"
    );
    $query->set( 'post_type', $pt );
}
}

afin de définir la valeur post_type droite.

0
Max Kondrachuk

Cela a fonctionné pour moi: 'rewrite' => array('slug' => '/')

0
Malki Mohamed