2

I am working on a plugin that creates lists. After creating a list, I wanted to remove the slug from the url

Post type:

$rewrite = [
        'slug'       => 'single-link',
        'with_front' => false,
        'pages'      => false,
        'feeds'      => false,
    ];
    $args    = [
        'label'               => esc_html__( 'Single Link', 'single-link' ),
        'labels'              => $labels,
        'supports'            => [ 'title' ],
        'hierarchical'        => false,
        'public'              => true,
        'show_ui'             => true,
        'show_in_menu'        => true,
        'menu_position'       => 15,
        'menu_icon'           => 'dashicons-admin-links',
        'show_in_admin_bar'   => false,
        'show_in_nav_menus'   => true,
        'can_export'          => true,
        'has_archive'         => false,
        'exclude_from_search' => true,
        'publicly_queryable'  => true,
        'rewrite'             => $rewrite,
        'capability_type'     => 'page',
        'show_in_rest'        => true,
    ];

    $args = apply_filters( 'single-link/post_type/args', $args );
    register_post_type( 'single-link', $args );

Remove the slug from the URL:

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

if ( 'single-link' != $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', 'remove_cpt_slug', 10, 3 );


function change_slug_struct( $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', 'single-link', 'page' ) );
}
}
add_action( 'pre_get_posts', 'change_slug_struct' );

(this code is from here)

Now after hitting publish, the slug /single-link/ gets deleted, but we always get a 404 when visiting the page. Changing/re-Saving the permalinks did not help. What am I doing wrong?

3 Answers 3

3
+100

The registering of the custom post type and the permalink modification is OK. The problem is with the WordPress rewrite rules that more than likely will match the "cleaned up" URL of your simple links to pages and it will set the pagename query var not name as your change_slug_struct() function assumed.

So change the function to this to account for all cases:

function change_slug_struct( $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', 'single-link', 'page' ) );
    } elseif ( ! empty( $query->query['pagename'] ) && false === strpos( $query->query['pagename'], '/' ) ) {
        $query->set( 'post_type', array( 'post', 'single-link', 'page' ) );

        // We also need to set the name query var since redirect_guess_404_permalink() relies on it.
        $query->set( 'name', $query->query['pagename'] );
    }
}
add_action( 'pre_get_posts', 'change_slug_struct' );
5
  • that helped, I didn't even need to change or refresh the permalinks. Thank you!!
    – Paranoia
    Commented Jan 29, 2018 at 18:27
  • that didn't fully work, if I have a page with a parent (eg. domain.com/parent/page) i get a 404. If I change it to domain.com/page (without the parent) then it works again. Any idea what this could be?
    – Paranoia
    Commented Jan 29, 2018 at 22:05
  • I'll change this back to the correct answer, if we have a solution. Unfortunately I am stuck :(
    – Paranoia
    Commented Jan 30, 2018 at 15:19
  • Yes. I haven't taken into account the case where there are child pages. Since your custom post type is not hierarchical, it is safe to exclude cases when there are child pages. I have modified my answer. Do let me know if it works and don't forget to market it as the right answer.
    – Vlad Olaru
    Commented Jan 30, 2018 at 20:04
  • you're a genius!!
    – Paranoia
    Commented Jan 30, 2018 at 20:42
2

You have to alter the perma structure. By default your custom post type's post will only be found wenether the url starts with the slug prefix. When changing the prefix you will have similar issues as when deleting it, have a look at this post.

To achieve removal of the post type slug prefix you should hook into single-link_rewrite_rules and iterate through those rules and remove the prefix there as well.

Note: changes in the perma structure may cause url conflicts.

1
  • @Paranoia not 100% sure what you mean with "use the page type". But with the rewrite_rules_array hook you can access all rules.
    – luukvhoudt
    Commented Jan 24, 2018 at 12:10
0

For multiple Custom Post Types adjust like this

     $query->set( 'post_type', array( 'post', 'custom1', 'page' ) && array( 'post', 'custom2', 'page' ) );

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.