3

That's strange issue I have on this one website. Similar to this problem and I am trying to get this fixed from last couple of weeks.

This website have latest WordPress installed and /%postname%/ permalink structure.

Sometimes, when I try to view a post, I get redirected to attachment post /?attachment_id=358 instead of the post itself. This happens on posts when post and the attachment have the same title.

Although I can make the post working again if I change the permalink of the post. But that's too late since this website publish and share posts automatically. And users get error when they do not get to the right post.

I already tried disabling all plugins for a while. None worked.

5

I think the reason for this is the get_page_by_path() check inside the WP_Query, because it's checking for both page and attachment slugs, in this case.

So if we have both an attachment and a post with the someslug postname and visit:

example.tdl/someslug

then get_page_by_path() will generate the following query:

SELECT ID, post_name, post_parent, post_type
FROM wp_posts
WHERE post_name IN ('someslug')
AND post_type IN ('page','attachment')

and we're therefore served the attachment's page instead of the post's page.

So this seems to be a core feature but not a bug generated by your plugins.

Workaround

Because of the permalink settings, the post request is handled like a page request.

We therefore have the pagename query variable constructed instead of the name query variable.

We can adjust the query variables, generated for the post request:

/**
 * Handle post requests correctly, in the case of the /%postname%/ permalink settings
 */
! is_admin() && add_filter( 'request', function( $query_vars )  
{
    if( 
           isset( $query_vars['pagename'] ) 
        && $post = get_page_by_path( $query_vars['pagename'], OBJECT, 'post' )
    ) {
        if( is_a( $post, '\WP_Post' ) )
        {
            // Add the 'name' query variable 
            $query_vars['name'] = $post->post_name;     

            // Unset the 'pagename' query variable
            unset( $query_vars['pagename'] );
        }
    }
    return $query_vars;
}, PHP_INT_MAX );

Here we check if a post exists with the pagename slug and if it exists, we construct the name query variable and finally unset the pagename query variable.

Now the post should be served instead of the attachment.

| improve this answer | |
  • Is this page in last line post_type IN ('page','attachment')? shouldn't it be post? Because my problem is with posts. So any suggestion to fix this issue. – Robert hue Oct 6 '15 at 9:42
  • Because of of your permalink settings, the pagename query variable is set, so your post *"walks" & "quacks" like a page, and WordPress will then first try to find the ID of that page through get_page_by_path(), and it succeeds. Workarounds are possible, e.g. like I worked on here recently. @Roberthue – birgire Oct 6 '15 at 10:16
  • 1
    I tried the new code and it's working now. Conflicting posts are accessible now. BTW shouldn't this be included in WordPress by default? Because a lot of people use /%postname%/ permalink settings. – Robert hue Oct 6 '15 at 10:59
  • 1
    great, yes it would be nice to have this core supported, because there are so many using this kind of permalink settings. Not sure if there's a ticket for this, haven't checked @Roberthue – birgire Oct 6 '15 at 11:03
  • 1
    you're welcome, it's always fun to work on puzzles like this one ;-) @Roberthue – birgire Oct 6 '15 at 11:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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