How can I exploit the wordpress template hierarchy to render a different post template depending on category name/slug? - wordpress

Apologies if this appears simple to some, but I have scaled high and low and I'm not finding a solution here to my problem, which is:
I have a website set up with Wordpress in which posts can fall under one of three categories: reviews, views, news - the slugs associated with each of these category names are the same.
Currently, calling up the web page of any individual post classified under any of these categories will see it rendered by the file single.php.
However, I want to make a slight adaption to the rendering of the post when it falls within the 'reviews' category. I have copied and renamed the original single.php file to single-post-reviews.php (no custom posts here, I will just confirm and I would like, if possible, to avoid child-theming here - not good practice, I know), but I am not seeing the new rendering from my new file.
I've also tried renaming to single-reviews.php which hasn't worked either - so could someone tell me what exactly I'm missing here?
Thanks,

WordPress Template Hierarchy for Single Posts doesn't factor in the current post category (likely due to the fact you can have multiple categories). Due to this, you have 2 viable options to your problem.
1) You can modify single.php to check for the post category, and if it's categorized under reviews, do something. This makes sense if you're just adding a small amount of markup in one or two places, or even hiding a few lines conditionally.
2) You can override the page template that's loaded based on the post's category using the single_template filter. Because I don't know exactly what you're doing, I'm going to elaborate more on this method. Take the following function:
add_filter( 'single_template', 'so51913799_review_template' );
function so51913799_review_template( $single_template ){
global $post;
if( has_category( 'reviews' ) ){
$single_template = get_stylesheet_directory() . '/single-post-reviews.php';
}
return $single_template;
}
If you put it in your functions.php file, it will make use of the has_category() function (I prefer this to in_category() since in_category just returns has_category anyways) and if it matches, it will update the $single_template variable to single-post-reviews.php. This assumes that the file is inside your /wp-content/themes/ACTIVE-THEME/ directory.

Related

How to change members per page in BuddyPress members directory

In BuddyPress, it shows 20 members per members directory page. I want to list 24 members per page with a pagination and sorting must work perfectly. I tried:
bp_has_members(bp_ajax_querystring('members').'per_page=24'))
It works but pagination and sorting are not working correctly.
For those like me wondering how to do this nowadays and ending here after searching with their fav engine, the proper way is to use a filter in bp-custom.php or the functions.php of your theme.
Cf. https://codex.buddypress.org/developer/using-bp_parse_args-to-filter-buddypress-template-loops/
For the member loop it would be something like :
function my_bp_members_per_page( $retval ) {
$retval['per_page'] = 24;
return $retval;
}
add_filter( 'bp_after_has_members_parse_args', 'my_bp_members_per_page' );
Bonus : this will still work if you use cache like WP Rocket.
Former method doesn't work with cache and logged in user.
You need an '&' for each additional argument.
Try:
bp_has_members(bp_ajax_querystring('members').'&per_page=24'))
To modify this file, you make a copy of it and put it into your child-theme
/your-child-theme/buddypress/members/members-loop.php

Merge comments between different posts

I need to replicate the behavior of this site:
http://www.theincipit.com/2013/11/la-notte-di-halloween-tost/9/
As you can see, I linked a "story" divided in various chapters (1-10). Every single chapter, though, displays the same list of comments. So you can comment every chapter but it will go automatically under the same list, displayed in every chapter.
In my site I have different posts grouped in different categories, and I''d like that the same posts form one category display the same list of comments (and when you comment from every post of that category, you update the same list)
Thanks!
Here's a start, anyway. Haven't tested this, yet.
add_rewrite for to get an extra querystring
Add a rewrite to the specific page (id as XX, below).
add_rewrite_tag('%chapter%','([^&]+)');
add_rewrite_rule('^story-slug/([^/]*)/?','index.php?page_id=XX&speaker=$matches[1]','top');
make a template for that specific page.
And create a page-xx.php where xx is the page ID (or slug) that will make use of an extra piece on the end of the url: /story-slug/1/ the 1 in this case. Don't forget to include the comments in this template!
In the post editor, write the whole thing as one entry, wrapping the chapters in [chapter id="X"]
Then, hide chapters that don't correspond to the url's chapter query, via shortcode.
add_shortcode('chapter', 'chapter_display')
function chapter_display($atts, $content) {
$current_chpater = $wp_query->query_vars['chapter'];
$chapter = $atts['id'];
if ($chapter == $current_chapter)
return $content;
}
Only thing missing from this solution is pagination across the top / bottom.
By continually referencing the same post, but showing different parts,
PS - don't forget to hit up wp-admin/options-permalink.php to flush the rewrite rules after you add the the add_rewrite_xxx functions to make sure that they take.

Wordpress Loop get_the_id()

I tried the following functions in header.php, footer.php, single.php etc.
var_dump(in_the_loop());
var_dump(get_the_id());
The first function gives false (meaning we are not in the loop) and the second function gives the post id every single time.
Description of get_the_id() from wordpress :
Retrieve the numeric ID of the current post. This tag must be within The Loop.
I just want a simple explanation what the hell is going on why do i get the post id if I call the function out of the loop !?
must is a little strong for get_the_id() ...delivers evil eye to Wordpress.
It works in the header and non-loop (confirmed).
Please note that post/page are essentially interchangeable in this conversation.
Think of WP this way -> You always have a post id in some way, all the time, every page, unless you do weird stuff or talk about non-page edge cases. When you are at the install root (such as site.com/) there are posts being called, something has to be displayed. There are other settings that will impact post/page such as static front page settings. On a category listing, if there are pages, I got the first ID returned before the loop.
On post/pages the page ID is (more or less0 set before the loop. This is a result of the URL (pretty or ?p=123 format) dictating the content. Using pretty names, the page at site.com/foo-bar/ will try to look up if there is content available via the permalink rules for "foo-bar". If there is content, the post ID is obtained. (simplified)
Later in the page build you get into the loop. However, before the loop you are also offered opportunities to change, sort, or augment the loop - such as changing the page IDs to be looped or sorting.
Regarding in_the_loop(), WP says
"True if caller is within loop, false if loop hasn't started or has ended." via http://codex.wordpress.org/Function_Reference/in_the_loop
in_the_loop() evaluates if the loop is in action (loop being key to the WP world). Also important - when you are in the loop WP can iterate over multiple page/post (IDs).
I don't have a 100% bulletproof explanation as to how the ID always shows, but when you dig into the API and various methods for hooking this might be a result.
I understand your confusion and agree with you. I think WP intended get_the_id() as a loop based tool, outside the loop you will get unpredictable results.
Hope that helps, I do enjoy working in WP, and I hope you do to.

How do I filter a block view by taxonomy argument in URL?

I have some block views in my sidebar that show events marked as a highlight happening in certain cities. Nodes are organized into cities using taxonomy.
When I load a node directly I have an URL like www.host.com/events/new-york/name-of-my-nice-event
I have some other page views that show teasers for all events in a certain city: www.host.com/events/new-york
Also I have some static pages that are valid for all cities, e.g. www.host.com/about-us
The sidebar blocks showing the highlights are available throughout the whole website. Now I want to make sure that the blocks in my sidebar only show those nodes for the selected city based on the taxonomy provided in the URL. (except for the static pages as there is no taxonomy in the URL, but those are not that important)
So far I tried to pass my view the taxonomy term as an argument using PHP as standard argument:
if (arg(1)) {
$term = arg(1);
return $term;
}
This works fine on the above mentioned page views (e.g. www.host.com/events/new-york). But when I load a node directly www.host.com/events/new-york/name-of-my-nice-event my block only shows the empty text.
I thought that arguments are indexed like this:
events/new-york/name-of-my-nice-event
^0 ^1 ^2
So I don't understand why arg(1) does not return new-york when I am viewing the node detail.
First of all, with path and path auto what you see is not always what you get.
Fx I could setup pathauto for my articles nodes to generate urls like this
content/article/[title]
So if I wanted the title I should use arg(2) right?
No! (arg(2) is actually NULL in this case.)
The reason is that the url that's generated by path auto is a fake url, that gets translated into a Drupal url. In the case above what I get is node/[nid]. So eventhough the node title i in the url, I can't get it by using arg(), but I can get the nid by using arg(1)
I can't guess what your urls map to, it depends how you have set up your site what modules you use etc.
A good advice if you do a lot of these context aware things, is to look into panels. It's made to be able to tell modules like views about the context which it is present. Like fx terms, nodes, etc, and you could use this to pass arguments into views.
Panels can do a lot more and is quite complex, but if you need to do a lot of this stuff, it is probably worth the investment.
Solution to my problem:
if (arg(0) == 'node' && is_numeric(arg(1))) {
$node = node_load(arg(1));
if (count($node->taxonomy) > 0) {
foreach ($node->taxonomy as $term) {
$term = $term->name;
}
}
$term = strtolower($term); // for some reason needed in my case
}
else {
$term = arg(1);
$term = str_replace('-', ' ', $term); // for some reason needed in my case
}
return $term;
While this was technically possible with Views 2 as described in some of the other answers, Views 3 has this integration built in.
You can create an argument for the taxonomy term id and then choose "Provide default argument". This will then give you an option for "Taxonomy Term ID from URL" and "Load default argument from node page..."
This will allow you to take the taxonomy of a page and pass that as an argument to your view block.
Note: Views 3 is currently in Alpha 3 but in my experience is at a relatively stable state and I am using it on production sites. If it has features like the one above that you find useful please use it, test it and submit bugs/patches if you encounter any issues!

Wordpress URL routing problem

I was wondering which is the best approach to get the catgeory ID when listing the posts within a particular category. Normally, the urls look something like this : www.example.com/?cat=4 and it is pretty easy to get the id. However, I really need the urls to be routed like this www.example.com/categories/hotels . wordpress provides an easy way to do the "pretty" routing, however all of the GET paramater information is lost this way. In this case, the $_GET variable is assigned nothing. I need to be able to say $category = $_GET["cat"] or something like that
What is the easiest approach ?
Can you use the Wordpress get_the_category function to grab the ID (from member variable cat_ID) once you're in the template?
See http://codex.wordpress.org/Function_Reference/get_the_category
e.g.
foreach((get_the_category()) as $category) {
$id = $category->cat_ID;
// do something with $id
}
The thing is that the guy might not really want to associate categories with post ids. In this case, there's the global $wp->query_vars array that contains all the data coming from the GET request even when the routing has been "prettified"
What about the category base setting in the backend? "Configuration" > "Permalinks" and there the last paragraph. See here for docs.

Resources