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

39

Il semble que toutes les ressources Web basées sur le sujet de la suppression d'un slug de type publication personnalisé, par exemple

yourdomain.com/CPT-SLUG/post-name 

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

'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 dans l'argument de réécriture ou ailleurs?

UPDATE: Il semble y avoir plusieurs façons de forcer cela à fonctionner avec regex. En particulier, la réponse de Jan Beck si vous êtes constamment disposé à surveiller la création de contenu pour vous assurer qu'aucun nom de page / publication contradictoire n'est créé ... Cependant, je suis convaincue qu'il s'agit d'une faiblesse majeure du noyau de WP, qui devrait nous être gérée. . 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: veuillez appuyer ce ticket de traçage en surveillant / promouvant ce dernier: enlace

    
posée TR3B 28.09.2015 - 18:18

10 réponses

56

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 lien permanent:

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 aurez 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' );

Modifiez simplement les "événements" selon votre type de publication personnalisé et vous êtes prêt à partir. Vous devrez peut-être actualiser vos liens permanents.

    
réponse donnée Nate Allen 30.09.2015 - 22:45
11

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

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

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

Vous pouvez le voir préfixer $args->rewrite['slug'] à la balise %$post_type% rewrite. On pourrait penser "définissons simplement le slug sur null then" jusqu'à ce que vous cherchiez quelques lignes:

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

Vous pouvez voir que la fonction a toujours attend une valeur slug qui n'est pas vide et utilise par ailleurs le type de publication.

    
réponse donnée Jan Beck 30.09.2015 - 16:01
11

É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é, accédez à Paramètres > Permaliens et réenregistrer vos paramètres , sinon la page 404 ne sera pas trouvée.

Cochez ici la meilleure solution: enlace

    
réponse donnée Mayank Dudakiya 12.04.2017 - 20:16
6

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 publication 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 écrasée par l'archive de type message qui utilise également le slug "calendrier".

  • 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é.
  • 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 susceptible d’exister similaire à cette réponse .
  • réponse donnée Jan Beck 02.10.2015 - 14:13
    2

    En regardant à travers les réponses ici, je pense qu’une solution meilleure, combinant certaines choses que j’ai apprises plus haut, ajoute à la détection automatique et à la prévention de la duplication des messages postaux.

    REMARQUE: Assurez-vous de changer le 'type_post_personne' 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 d'article personnalisé en les définissant sur "faux" lors de l'enregistrement de l'article:

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

    Étape 2: ajoutez manuellement nos réécritures personnalisées au bas des réécritures WordPress de notre type custom_post_type

    .
    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 souhaiterez 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: créez à nouveau des liens permanents vers votre type de message personnalisé "joli"

    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 conflictuelle (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 de publication

    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 l'implémentation de cette solution. Assurez-vous de vérifier d’abord les doublons.

    J'adorerais recevoir des nouvelles de tous ceux qui nous donneront l'occasion de voir si cela a bien fonctionné pour eux aussi.

        
    réponse donnée Matt Keys 06.10.2017 - 00:51
    0

    Vous n'avez pas besoin de tant de code dur. Utilisez simplement un plugin léger:

    Il a des options personnalisables.

        
    réponse donnée T.Todua 25.02.2017 - 23:12
    0

    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 correcte.

        
    réponse donnée Max Kondrachuk 01.03.2017 - 12:50
    0

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

        
    réponse donnée Malki Mohamed 03.05.2017 - 18:39
    0

    Pour tous ceux qui lisaient ceci et qui rencontraient des problèmes avec les publications pour enfants, 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 de pages comportant deux niveaux (messages enfants) de manière un peu différente de ce qu’elle traitait de trois niveaux plus profonds (enfants de messages enfant).

    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-nom / post-enfant / post-petit-enfant, je ne peux pas utiliser post-nom / post-enfant / 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 vous permet de vous rediriger vers le poste approprié. À trois niveaux, ça ne marche 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 et ainsi de suite afin d’obtenir le permalien qui convient. Cette partie n’est pas trop compliquée et vous trouverez des exemples de gens qui le font ailleurs.

    La prochaine étape consiste toutefois à modifier 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 afin que, 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 jetterait 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);
    

    En espérant que cela aide quelqu'un d'autre, je ne pouvais rien trouver d'autre concernant les messages relatifs aux enfants des enfants et le retrait de la limace de ceux-ci.

        
    réponse donnée Moe Loubani 29.05.2017 - 05:34
    -2

    Vous pouvez le faire très simplement.

    1) Copiez cette fonction dans le functions.php :

    de votre thème.
    function changeURL ($id)
    {
        /* Get the slug you want to remove. */
        global $post;
        $slug = get_post($post)->post_name;
    
        $post_type = get_post_type ($id);
        $standard_posts = array("post", "page", "attachment", "revision", "nav_menu_item");
        /* 
            If the type of the current post is a custom one, use Javascript to
            replace the $slug for the default URL of the post.
        */
        if (!in_array ($post_type, $standard_posts))
        {
            echo '<script type="text/javascript">
                var stateObj = { register: "' . $slug . '" };
                history.pushState(stateObj, "ignore_this", "../?p='.$id.'");
                </script>';
        }
    }
    


    2) Appelez cette fonction sur le single.php de votre thème situé sous le while de la boucle:

    <?php /* The loop */ ?>
    <?php while ( have_posts() ) : the_post();?>
    
        <?php changeURL (get_the_ID ()); ?>
        /* etc. */
    
    <?php endwhile; ?>
    


    Et laissez le Javascript faire la magie :)

    Mise à jour:

    Résolution des inconvénients signalés par @kraftner dans les commentaires. Désormais, changeURL() remplacera le lien permanent par l’URL par défaut dans la barre d’adresse.

        
    réponse donnée Daniel Muñoz Parsapoormoghadam 03.10.2015 - 11:34

    Lire d'autres questions sur les étiquettes