I am working on a project where I need to be able to change the template being used if a given shortcode is used. To complicate things more, the plugin must also be able to rewrite $query if this same shortcode is called.

I believe that I am running into issues in when various parts of the core exec vs. when shortcodes run, but I can't find the right information in the Codex to verify or debug the issue. Currently, my implementation neither modifies $query nor does it redirect the template.

Basically, the shortcode works (or, in this case, does not work) as follows:

  1. Shortcode is called
  2. Based on what info is in shortcode, args are generated to retrive some posts
  3. These args are assigned to a global variable, let's call it $custom, within the shortcode function
  4. Also within the shortcode, I hook template_redirect with get_home_template() as the argument
  5. Also in shortcode function, pre_get_posts is hooked with a function that assigns $query to new new WP_Query( $custom )

Like I said, I'm quite sure it's an order of exec issue, but I'm not sure where to look in order to figure out what needs to be modified. Any suggestions would be greatly appreciated!

  • Would it not be simpler to do wp_redirect() on a url that your shortcode php code could construct from its info. That url would use the new template and run the new query. – user27457 May 13 '13 at 0:46
  • In other words, pass through GET/POST all of the relevant info to generate the necessary page from scratch? If so, you're right. That would be much easier... let me play with that for a bit. – Dan May 13 '13 at 3:25
  • @MagentaCuda thinking about it, that would work in every way except that it would mess up the URL that the end user sees. I suppose it's not a huge deal, but I would rather it be transparently implemented if possible. – Dan May 13 '13 at 4:05

By the time your shortcode runs on the the_content hook (usually) the main query has executed, the pre_get_posts hook has fired for the main query, and the template_redirect hook has fired.

You won't be able to hook to template_redirect or alter the main query (if that is what you need) without somehow getting your shortcode to run much earlier than shortcodes normally would, which means parsing shortcodes in your pre_get_posts hook callback or even earlier, depending on the details of what you are trying to do.

And that probably means retrieving the posts (you don't have access to post content at the pre_get_posts stage), parsing the shortcodes, and then retrieving the posts again with the query alterations. That is a pretty heavy load.

It sounds to me like you are trying to get shortcodes to serve a function they aren't really meant to serve. A shortcode is a BB-Code-like post content formatting and display function not an alter the Loop and redirect function.

Maybe you'd have better luck if you were to explain the result you wanted rather than ask how to implement a particular solution.


As @s_ha_dum said, shortcodes are views, a late result of a query, not its precondition.

The only way to do what you are asking for would be parsing the shortcode long before the query is set: on save_post for example. Then you would have to evaluate the arguments for the query filter, store them in a separate option and use that option value in pre_get_posts to avoid a second query.

But even that approach would be incompatible with itself: Another shortcode working the same way would break the first one.

This smells like a XY problem. I guess a post meta field or just a custom post template selectable from a metabox would fit better.

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.