How to change Wordpress' default posts permalinks programmatically?
Asked Answered
W

3

7

In the backend of Wordpress I use the default http://localhost/sitename/example-post/ value for creating permalinks.

For custom post types I defined a custom slug this way, here is services for example:

register_post_type( 'service',
    array(
        'labels'      => array(
            'name'          => __( 'Services' ),
            'singular_name' => __( 'Service' )
        ),
        'public'      => true,
        'has_archive' => true,
        'rewrite'     => array(
            'slug'       => 'services',
            'with_front' => true
        ),
        'supports'    => array(
            'title',
            'editor',
            'excerpt',
            'thumbnail'
        ),
        'taxonomies'  => array( 'category' ),
    )
);

It creates services/post-name.

I also use this hook to create a custom page to create a custom page permalink:

function custom_base_rules() {
    global $wp_rewrite;

    $wp_rewrite->page_structure = $wp_rewrite->root . '/page/%pagename%/';
}

add_action( 'init', 'custom_base_rules' );

It creates page/post-name

Now the only thing I need to do is to create another custom permalink path for the normal Wordpress posts.

So the outcome world be for the post type of post:

post/post-name

I can't use the backed for this because I already defined a default way of handling the permalinks. I already managed to rewrite the paths of custom post types and pages...

How do I rewrite the normal post post type permalink path in Wordpress programmatically?

Woothen answered 20/9, 2018 at 14:51 Comment(0)
W
-2

The permalink_structure property suggested by GentlemanMax did not work for me. But I found a method that does work, set_permalink_structure(). See code example below.

function custom_permalinks() {
    global $wp_rewrite;
    $wp_rewrite->page_structure = $wp_rewrite->root . '/page/%pagename%/'; // custom page permalinks
    $wp_rewrite->set_permalink_structure( $wp_rewrite->root . '/post/%postname%/' ); // custom post permalinks
}

add_action( 'init', 'custom_permalinks' );
Woothen answered 24/9, 2018 at 7:56 Comment(6)
This does exactly the samething as setting up the permalinks in the admin dashboard though... It prepends /post/ to categories, and everything as well.Confluent
This function sets a page path and a different post path. Setting it up in the backend allows you to only use one path.Woothen
Yeah, this messes up the custom post type links. Figured out an another solution https://mcmap.net/q/1539831/-how-to-change-wordpress-39-default-posts-permalinks-programmaticallyWaldenses
In my case this was the solution Elepi. Maybe you have to visit the permalink page to refresh them?Woothen
affirmative, Eselpi's solution also worked for me, but I had to visit the permalink page to refresh them.Angelika
Thanks, exactly what I wanted.Pourparler
W
6

You need to do it in two steps.

First enable rewrite with 'with_front' => true for the buildin post registration

add_filter(
    'register_post_type_args',
    function ($args, $post_type) {
        if ($post_type !== 'post') {
            return $args;
        }

        $args['rewrite'] = [
            'slug' => 'posts',
            'with_front' => true,
        ];

        return $args;
    },
    10,
    2
);

This way urls like http://foo.example/posts/a-title work but generated links in are now wrong.

Links can be fixed by forcing custom permalink structure for the buildin posts

add_filter(
    'pre_post_link',
    function ($permalink, $post) {
        if ($post->post_type !== 'post') {
            return $permalink;
        }

        return '/posts/%postname%/';
    },
    10,
    2
);

See https://github.com/WordPress/WordPress/blob/d46f9b4fb8fdf64e02a4a995c0c2ce9f014b9cb7/wp-includes/link-template.php#L166

Waldenses answered 25/9, 2019 at 13:42 Comment(1)
Should note that with this approach your canonical URLs are going to be off since WP still thinks your posts exist at the root.Strobotron
L
0

Posts have to use the default permalink structure, they do not have a special entry in the rewrite object in the same way that pages or custom post types do. If you want to change the default structure programmatically, you can add something like this to your hook.

$wp_rewrite->permalink_structure = '/post/%postname%';

I'm not super clear what you mean when you say

I can't use the backed for this because I already defined a default way of handling the permalinks. I already managed to rewrite the paths of custom post types and pages...

It sounds as though you're overriding the default behavior for permalinks everywhere except for posts so if you changed the default it would likely only affect posts anyway.

Lamkin answered 20/9, 2018 at 15:30 Comment(1)
If I change the default setting for the permalink structure it also effects the custom post type permalinks from what I can remember. But that's not what I want, I want to use custom paths for both.Woothen
W
-2

The permalink_structure property suggested by GentlemanMax did not work for me. But I found a method that does work, set_permalink_structure(). See code example below.

function custom_permalinks() {
    global $wp_rewrite;
    $wp_rewrite->page_structure = $wp_rewrite->root . '/page/%pagename%/'; // custom page permalinks
    $wp_rewrite->set_permalink_structure( $wp_rewrite->root . '/post/%postname%/' ); // custom post permalinks
}

add_action( 'init', 'custom_permalinks' );
Woothen answered 24/9, 2018 at 7:56 Comment(6)
This does exactly the samething as setting up the permalinks in the admin dashboard though... It prepends /post/ to categories, and everything as well.Confluent
This function sets a page path and a different post path. Setting it up in the backend allows you to only use one path.Woothen
Yeah, this messes up the custom post type links. Figured out an another solution https://mcmap.net/q/1539831/-how-to-change-wordpress-39-default-posts-permalinks-programmaticallyWaldenses
In my case this was the solution Elepi. Maybe you have to visit the permalink page to refresh them?Woothen
affirmative, Eselpi's solution also worked for me, but I had to visit the permalink page to refresh them.Angelika
Thanks, exactly what I wanted.Pourparler

© 2022 - 2024 — McMap. All rights reserved.