I use this to display all posts in all categories.
$args_cat = array(
// order by category name ascending
'orderby' => 'name',
'order' => 'ASC',
// get only top level categories
'parent' => 0
);
$categories = get_categories($args_cat);
// Full posts query
// if there are categories filled with posts
if (!empty ($categories) && !is_wp_error( $categories )) {
foreach ($categories as $category) {
// Query all posts by slug inside each category
$args_category_posts = array(
'post_type' => 'post',
// The category slug and category name we get from the foreach over all categories
'category_name' => $category->slug
);
$query = new WP_Query($args_category_posts);
if ($query->have_posts()) {
while ($query->have_posts()) {
$query->the_post(); ?>
<article class="<?php echo $category->slug ?>-article">
<h2 class="<?php echo $category->slug ?>-article-title">
<a href="<?php echo get_permalink() ?>"><?php echo get_the_title() ?></a>
</h2>
<p class="<?php echo $category->slug ?>-post-info">
<?php the_time('d. m. Y') ?>
</p>
<div <?php post_class() ?> >
<?php the_content(); ?>
</div>
</article> <?php
}
} // end loop
} // end foreach
wp_reset_postdata() ;
} // end if there are categories filled with posts
Having read this, this, this and this I am wondering if I am doing the right thing below.
// Transient API all categories and all posts
$query_categories = get_transient('cached_categories');
if ( false === $query_categories){
$args_cat = array(
// order by category name ascending
'orderby' => 'name',
'order' => 'ASC',
// get only top level categories
'parent' => 0
);
// Instead of caching a WP Query I cache 'get_categories($args_cat)', OK to use it like this?
$query_categories = get_categories($args_cat);
set_transient('cached_categories', $query_categories, DAY_IN_SECONDS );
}
// Full posts query
// if there are categories filled with posts
if (!empty ($query_categories) && !is_wp_error( $query_categories )) {
foreach ($query_categories as $category) {
$query_category_posts = get_transient('cached_posts');
if ( false === $query_category_posts ){
// Query all posts by slug inside each category
$args_category_posts = array(
'post_type' => 'post',
// The category slug and category name we get from the foreach over all categories
'category_name' => $category->slug
);
// Here I cache the WP_Query, though this runs for all categories.
// So am I storing multiple transients here?
$query_category_posts = new WP_Query($args_category_posts);
set_transient( 'cached_posts', $query_category_posts, DAY_IN_SECONDS );
}
if ($query_category_posts->have_posts()) {
while ($query_category_posts->have_posts()) {
$query_category_posts->the_post(); ?>
<article class="<?php echo $category->slug ?>-article">
<h2 class="<?php echo $category->slug ?>-article-title">
<a href="<?php echo get_permalink() ?>"><?php echo get_the_title() ?></a>
</h2>
<p class="<?php echo $category->slug ?>-post-info">
<?php the_time('d. m. Y') ?>
</p>
<div <?php post_class() ?> >
<?php the_content(); ?>
</div>
</article> <?php
}
} // end loop
} // end foreach
wp_reset_postdata() ;
} // end if there are categories filled with posts
The output is ok, all categories and posts display fine, though are the categories and posts properly cached now?
In the code I commented the two places where I set the transient but am not sure if this can be used with get_categories()
or inside the foreach
for all posts in the category.
Edit
The transient works for get_categories()
. The var_dump
output shows me an array of the WP_Term objects holding the categories available.
$query_categories = get_categories($args_cat);
var_dump($query_categories);
set_transient('cached_categories', $query_categories, DAY_IN_SECONDS );
Edit
The transient inside the foreach
is only getting the first category and its posts and repeating that for the number of categories. Other categories than the first are not present, this presumably because the same transient gets called for the amount of number of categories and after the first round of foreach
it is full and hence the loop only shows the posts form the first category.
Now how can I make a new transient that holds the posts per category on every cycle of the foreach
for the number of categories?
Totally new to the Transient API and trying to make good use of it. Trying to tune the code and keep to best practices, if this is all bad use with errors lurking or no use of all since it does not work please do let me know. A bit of guidance or if I have grasped "the way" to use transients would be highly appreciated.
Solution
Per this answer I had to give the created transient for each category the category name (slug). Otherwise only the first category gets stored in the transient and once it is full for the second cycle it will not be changed. Hence only the posts from the first category were showing.
Only using $category
for the transient variable was not working since $category
is an object and a string was needed, so I changed it to $category->slug
and now it works.
This was done in both places, getting and setting the transient. Thank you!
// Transients API all categories and all posts
$query_categories = get_transient('cached_categories');
if ( false === $query_categories){
$args_cat = array(
// order by category name ascending
'orderby' => 'name',
'order' => 'ASC',
// get only top level categories
'parent' => 0
);
// Instead of caching a WP Query I cache 'get_categories()'.
$query_categories = get_categories($args_cat);
// var_dump($query_categories);
set_transient('cached_categories', $query_categories, DAY_IN_SECONDS );
}
// Full posts query
// if there are categories filled with posts
if (!empty ($query_categories) && !is_wp_error( $query_categories )) {
foreach ($query_categories as $category) {
// var_dump($category);
$query_category_posts = get_transient('cached_posts_' . $category->slug );
if ( false === $query_category_posts ){
// Query all posts by slug inside each category
$args_category_posts = array(
'post_type' => 'post',
// The category slug and category name we get from the foreach over all categories
'category_name' => $category->slug
);
// Here I cache the WP_Query, though this runs for all categories.
// Because of that the '$category->slug' is used to serve a string and not an object.
$query_category_posts = new WP_Query($args_category_posts);
set_transient( 'cached_posts_' . $category->slug , $query_category_posts, DAY_IN_SECONDS );
}
if ($query_category_posts->have_posts()) {
while ($query_category_posts->have_posts()) {
$query_category_posts->the_post(); ?>
<article class="<?php echo $category->slug ?>-article">
<h2 class="<?php echo $category->slug ?>-article-title">
<a href="<?php echo get_permalink() ?>"><?php echo get_the_title() ?></a>
</h2>
<p class="<?php echo $category->slug ?>-post-info">
<?php the_time('d. m. Y') ?>
</p>
<div <?php post_class() ?> >
<?php the_content(); ?>
</div>
</article> <?php
}
} // end loop
} // end foreach
wp_reset_postdata() ;
} // end if there are categories filled with posts