web-dev-qa-db-fra.com

Permaliens pour CPT rompt les permaliens en pages

J'ai un CPT pour lequel j'aimerais avoir les permaliens 'root':

Donc pour la page: 'Foo Bar', j'aimerais que l'URL soit la suivante:

https://example.org/foo-bar

J'ai découvert que j'y suis parvenu en enregistrant le CPT avec la ligne suivante dans la variable args pour register_post_type( 'my_CPT', $args );:

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

Cependant ... Lorsque j'ajoute cela, mes liens permanents pour mes pages ne fonctionnent pas. Je leur donnerais idéalement ces permaliens:

https://example.org/page/some-page

Comment je fais ça?

2
Zeth

Les pages sont codées en dur pour être la possibilité d'analyse par défaut pour n'importe quelle URL (ou pour le dire différemment, si rien ne correspond, wordpress essaiera d'y trouver une page).

Par conséquent, il est déconseillé de mettre une structure permalien sans "préfixe", mais si vous le voulez vraiment, ajoutez simplement une page avec un slug de "page" et faites de toutes les autres pages ses fils. Cela fonctionnera très bien si vous n’avez pas beaucoup de pages et que vous aurez zéro code qui pirate lors de l’analyse et de la génération de liens permanents à vous soucier de;)

2
Mark Kaplun

WordPress utilise Rewrite Rules pour analyser la demande. Cela signifie que si la demande correspond à l'une des règles, elle sera analysée à l'aide de cette règle.

La règle pour les pages est l'une des dernières règles permettant d'attraper la plupart des demandes qui ne correspondaient à aucune règle antérieure. Donc, si vous ajoutez votre CPT sans slug, la règle des pages ne sera pas activée ...

Une façon de résoudre ce problème consiste à enregistrer CPT avec un slug, puis à modifier le comportement de leurs liens et de leurs WP. Voici le code:

function register_mycpt() {
    $arguments = array(
        'label' => 'MyCPT',
        'public' => true,
        'hierarchical' => false,
        ...
        'has_archive' => false,
        'rewrite' => true
    );
    register_post_type('mycpt', $arguments);
}
add_action( 'init', 'register_mycpt' );

Maintenant, les URL de ces publications ressemblent à celles-ci:

http://example.com/mycpt/{post_name}/

Mais nous pouvons facilement changer cela en utilisant le filtre post_type_link:

function change_mycpt_post_type_link( $url, $post, $leavename ) {
    if ( 'mycpt' == $post->post_type ) {
        $url = site_url('/') . $post->post_name . '/';
    }

    return $url;
}
add_filter( 'post_type_link', 'change_mycpt_post_type_link', 10, 3 );

Maintenant, les URL seront correctes, mais ... Elles ne fonctionneront pas. Ils seront analysés à l'aide de la règle de réécriture des pages et provoqueront une erreur 404 (car aucune page ne contient une telle URL). Mais nous pouvons résoudre ce problème aussi:

function try_mycpt_before_page_in_parse_request( $wp ) {
    global $wpdb;

    if ( is_admin() ) return;

    if ( array_key_exists( 'name', $wp->query_vars ) ) {
        $post_name = $wp->query_vars['name'];

        $id = $wpdb->get_var( $wpdb->prepare(
            "SELECT ID FROM {$wpdb->posts} WHERE post_type = %s AND post_name = %s ",
            'mycpt', $post_name
        ) );

        if ( $id ) {
            $wp->query_vars['mycpt'] = $post_name;
            $wp->query_vars['post_type'] = 'mycpt';
        }

    }
}
add_action( 'parse_request', 'try_mycpt_before_page_in_parse_request' );

PS Est-il sage d'utiliser ce code? C'est une autre question. Cela change le comportement de WP de manière assez importante, donc ça peut être un peu délicat. Mais s'il y a vraiment un besoin, vous pouvez le faire ...

Avertissement: Ce code fonctionnera correctement pour les CPT non hiérarchiques, mais vous pouvez l'adapter pour fonctionner également pour les hiérarchiques ...

1