• I’m sure there is a way to do this but I can’t figure it out. I want to display a post based on variables that I gather (from GET and $wpdb) rather than using a permalink – i.e. the same URL would produce a different post depending on the circumstances. Is there a way to do this such that I don’t need to change a great deal of code in the displaying of the post (i.e. I can still use the standard .php files with the_title, the_content etc., but just with an added function somewhere to change the post which all the functions refer to)?

    So I could display the posts the usual way (with permalinks), but also have another page which works out which post to show the viewer based on some internal logic rather than solely based on the URL?

Viewing 7 replies - 1 through 7 (of 7 total)
  • You could register a function on pre_get_posts in your functions.php and change the given result using other parameters too, but that seems not very serach-engine friendly..
    Can you provide a more specific case?

    Thread Starter _F12

    (@_f12)

    Gotcha. I’ve been having a look over pre_get_posts and the related documentation pages but I’m still not sure I’ve got a handle on it.

    function query_question( $query ) {
    	$var = 42 //Set based on other logic in real case
    	$query->set ('p', $var);
    }
    
    add_action( 'pre_get_posts', 'query_question' );

    I’ve got the above code in the template for my custom post_type (single-post_type.php), but it is still just displaying the post to which the permalink refers rather than the post with id = 42. (Obviously the 42 is just a placeholder at the moment so I can get a proof of concept, then I will add in the other logic). Am I completely misunderstanding the functions and WP_Query here?

    As far as SEO it is not a big concern for this specific section of the blog.

    Moderator bcworkz

    (@bcworkz)

    Your code is correct in of itself, but it’s in the wrong place. By the time your template loads, ‘pre_get_posts’ action has already come and gone, it’s too late to alter the query on templates.

    The code belongs on functions.php or in a plugin.

    Thread Starter _F12

    (@_f12)

    Doiii, I don’t know what I was thinking. Of course, thanks.

    I’m at a bit of a loss now for how best to approach this problem. I’ll try to explain what I want to achieve as best I can.

    Basically each person has a certain list of competencies that they need to go through, represented by a custom post-type. So essentially I can have a database field which represents the competencies they need and their order, and then retrieve which post I should be showing based off two things: the user_id and the number they have reached.

    So let’s say user “mwahlberg” is on stage 3, the database tells us to show him the post (custom post-type) with id=523. Ideally I would have as the link either site.com/competency/3 (pulling up id=523 internally, rather than in the URL) or similar. For another user though, “jtimberlake”, that same permalink would pull up id=445 because the database has a different set of required competencies for him. Obviously the whole set would be restricted to registered users (not a problem for this specific application).

    What is the best way to achieve this? I can manage it using some GET variables in the function but I think there is a better more abstracted way to do it that goes along more with the WordPress way of doing things. Can anyone give me some pointers on where to look/read to get started?

    Moderator bcworkz

    (@bcworkz)

    It’s hard to keep the processing order in mind, it’s not all that well documented (though templates coming after queries is sort of obvious ?? ) In a similar vein, using ‘pre_get_posts’ as a sort of rewrite function is fine, but the initial permalink may need to resolve to an actual resource or it might 404 before reaching ‘pre_get_posts’… I think. Maybe not, easy enough to test, but I’ll leave that to you.

    As for best approach, you of course need to store competencies somewhere. Their nature could dictate the best location. If there is a limited set of competencies, they could be stored in a structured array in wp_options. If they are custom built for each user, then they should be stored in user_meta, again as an array.

    The array could just be a sequence of post IDs. The stage number could be the index into the array. (index 0 might be a generic placeholder page so the real sequence can start with 1) If these are predefined in wp_options, the arrays could be keyed by course name or something. Under each course is that same sequence of ID’s for that course.

    To deliver the correct post, you either get the course name or the actual sequence from user meta. You can get the stage/index number from query vars because it is part of the permalink structure. Then grab the ID out of the array and set the “p” query var.

    All that is fairly straight forward, but like most coding projects, most of the work is in building an UI where new sequences can be easily defined and assigned without needing to change the code. Still, establishing the underlying data structure is an important first step that requires careful consideration, as changing it later can be difficult.

    Thread Starter _F12

    (@_f12)

    Yeah, I don’t think I’ll have too much trouble defining the data structures and setting up the UI around that (although, as you said, it will be time-consuming).

    The problem I am having is still around the URL and communicating the post to show. I can set the post-id given a post-type, but I still can’t figure out how to have a URL like /competencies/4 and have that actually show the desired competency. The first issue is decoding the URL to something that I can interpret and perform logic based on (first, calling the displaying the relevant page-template for competencies, then querying the post which corresponds to 4 for that user). The best I can achieve at the moment is redirecting the user to a specified post if they go to any other post (also changes the header location for some reason rather than just changing the displayed post).

    function query_competency($query ) {
    	if ($query->get('post_type') == 'comp_competencies') {
    		$query->set('p', 43); //Logic to decide which post to be added later
    	}
    }
    
    add_action( 'pre_get_posts', 'query_competencies' );

    The above is the code I’m using to try and build an understanding at this preliminary stage. All it can do at the moment is, if I’m viewing any post singly that is of the specified post_type, then it redirects me to the URL of the post with id=43.

    I suspect I need to play around with the mod_rewrite rules to get it to interpret my URL input but even after that I am still stuck for what to be doing, even if I set the permalink rules to default (with standard GET vars) for the time being.

    Moderator bcworkz

    (@bcworkz)

    Sorry for the late reply, I’ve been away.

    I’m afraid much of this is something you’ll need to work out for yourself, but maybe the following will get you pointed in the right direction.

    mod_rewrite and/or the WP Rewrite API may figure in to your scheme, depending on exactly how your desired URL structure appears and how it relates to other possible URLs unrelated to the lesson sequences. The main goal here really is to avoid having the default request parser returning 404s and getting the various URL fragments assigned to the correct query vars.

    If that is achieved, everything else related to returning the correct page can be achieved in the ‘pre_get_posts’ callback. All the URL parameters should be available as query vars. Based on that you enter a lookup table or whatever to get the proper page ID and set the ‘p’ query var with it. You may need to then unset the establishing query vars to avoid query conflicts which would cause a 404. The ID alone is of course adequate to query for the correct page.

    As an example, lets say your URL is example.com/valueA/value3/valueZ9/. Through some rewrite process, the URL becomes example.com/index.php?var11=valueA&varJK=value3&varR5=valueZ9. This will cause all the values to be assigned to query vars named in the form ‘var*’.

    If you have created a good lookup table, you can set the ‘p’ query var simply with $query->set('p', $lookup[$query->get('var11')][$query->get('varJK')][$query->get('varR5')]);. Of course, for robust code, you should first validate all the values from the URL to ensure they relate to values that are actually indexes of the lookup table.

    The ‘p’ query var is not the only thing you can set from ‘pre_get_posts’. You can set any argument used for WP_Query through this action. For custom applications, ‘meta_query’ and ‘tax_query’ are very powerful, assuming you’ve established useful meta and taxonomy data associated with your posts.

Viewing 7 replies - 1 through 7 (of 7 total)
  • The topic ‘Changing displayed post’ is closed to new replies.