0

I'm creating a website for a photo project where the artist took photos and did interviews every day of the year. As such, I'd like to keep the URL structure for posts as simple as possible -- meaning mysite.com/month/day, or photoproject.com/12/5.

When I set my posts permalinks to /%monthnum%/%day%, the links are generated correctly, but index.php is used to serve the posts instead of single.php. If I change the permalinks to include other more "unique" information, such as the post title, then single.php is used.

I'm assuming this has something to do with the fact that as far as wordpress is concerned, my URL format is not unique enough per post. Anybody have a solution/workaround?

EDIT: As the comments below outlined, my URLs are obviously being interpreted as date archives and displayed as such. In this case, my question might be "is there a way to tell wordpress not to interpret these as date archives?"

4
  • 1
    WordPress is parsing those requests as date archives. What happens if you have two posts on the same day? Or the same day but different years? You need a less ambiguous structure.
    – Milo
    Dec 17, 2016 at 0:32
  • I realize that theoretically I "could" have multiple posts on the same day or different years, but the nature of this particular project means that it will never happen. In this particular case, a less ambiguous structure is not at all required. I guess the question might be better phrased as, "how can I get wordpress to interpret my URL as a post instead of as a date archive?"
    – Mrweiner
    Dec 17, 2016 at 0:34
  • WP doesn't know that, those URLs match the date archive rewrite rules, so WordPress is loading a date archive. It's expected behaviour, and perfectly standard, your problem is that WordPress is doing what it's supposed to, and your expectations don't match. Add a date.php to your theme and you'll see that's the case. This is not a bugfix/workaround
    – Tom J Nowell
    Dec 17, 2016 at 0:37
  • I'm new to wordpress, so I didn't realize it was being interpreted as a date archive. That definitely explains the page that is being shown. That being said, I do indeed want "custom URL permalinks", and that is what I am trying to define here with the date. Is there a way to tell wordpress that these URLs are not in fact date archives, or is the only method to create a date.php? From my cursory understanding, it seems that rendering custom fields would be easier in single.php.
    – Mrweiner
    Dec 17, 2016 at 0:44

1 Answer 1

0

You could force WP's hand here with a filter and action. Doing this doesn't give me the warm fuzzies- I haven't really tested it, so it may have unintended side-effects. Maybe there's a better way to do this.

The first step (after setting permalinks to /%monthnum%/%day%/) is to hook parse_query and test for requests where monthnum and day are set. When that's true, we unset some things and set some other things, to trick WP into thinking this is a singular post request. Maybe this will break other date archives, I didn't test that!

function wpd_parse_query( $query ){
    if( isset( $query->query_vars['monthnum'] )
     && isset( $query->query_vars['day'] )
     && 0 != $query->query_vars['monthnum'] ){
        unset($query->is_archive);
        unset($query->is_date);
        unset($query->is_day);
        $query->is_single = 1;
        $query->is_singular = 1;
    }
}
add_action( 'parse_query', 'wpd_parse_query' );

The next step is to filter post_limits, and test for the unusual condition of it being a singular post with non-zero monthnum. In this case we set it to return the first post, in the case that there's more than one.

function wpd_post_limits( $limit, $query ) {
    if( $query->is_main_query()
     && $query->is_singular()
     && isset( $query->query_vars['monthnum'] )
     && 0 != $query->query_vars['monthnum'] ){
        return 'LIMIT 1';
    }
    return $limit;
}
add_filter( 'post_limits', 'wpd_post_limits', 10, 2 );

You could just leave that part out if you don't care about that case- if the template uses The Loop, it will just repeat the contained markup for each post, though all other data outside the loop will refer to the first post- title, shortlink, body classes, etc..

Now these requests should be interpreted as singular posts, template tags should behave accordingly, and the single template will be loaded.

3
  • Thanks for this suggestion! After spending more time with WP, I realized that the suggestion by @tom-j-nowell about using date.php was probably the right way to go. I just added a check before the loop so that if $wp_query->post_count == 1 (ie a date url such as /12/15) then it would print something like what I was using for single.php, otherwise it should display something more like an archive page. This seems like the proper answer for overriding what I was asking for, though.
    – Mrweiner
    Dec 19, 2016 at 23:39
  • @Mrweiner the problem with just using date.php is that it's a singular post in the context of an archive, so a lot of the template tags won't output correctly, like the title tag, canonical link, next/prev links, body class, etc..
    – Milo
    Dec 20, 2016 at 2:08
  • Good point. This is indeed working for me, with the caveat that I had to add && 0 != $query->query_vars['day'] to wpd_parse_query. I'm still taking advantage of the monthly archives, but since $query->query_vars['day'] is set on those pages -- although equal to 0 -- the pages were rendering as blank.
    – Mrweiner
    Dec 22, 2016 at 18:22

Your Answer

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

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