wordpress - get_catgories custom ordering - php

I am using get_categories to show posts in a category in my frontpage, but I want to order categories as i defined,Like:
$cat_order = 5,2,4,1,3 //order by category ID
or
$cat_order = cat5,cat2,cat4,cat1,cat3 // order by cat name
below is my current code which order cat by name, ASC
<?php
//for each category, show all posts
$cat_args=array(
'orderby' => 'name',
'order' => 'ASC'
);
$categories=get_categories($cat_args);
foreach($categories as $category) {
$args=array(
'showposts' => -1,
'category__in' => array($category->term_id),
'caller_get_posts'=>1
);
$posts=get_posts($args);
if ($posts) {
echo '<p>Category: <a href="' . get_category_link( $category->term_id ) . '" title="' . sprintf( __( "View all posts in %s" ), $category->name ) . '" ' . '>' . $category->name.'</a> </p> ';
foreach($posts as $post) {
setup_postdata($post); ?>
<article >
<h3><?php the_title(); ?></h3>
<?php the_content(); ?>
</article>
<?php
} // foreach($posts
} // if ($posts
} // foreach($categories
?>

There's no way to sort this within the query itself. You'll have to sort it yourself once you get the results back. To sort an array by custom criteria, use the usort function. Here's an example:
$categories = get_categories();
$cat_order = array(5, 2, 4, 1, 3);
usort($categories, function ($a, $b) {
return ((int) array_search($a->term_id , $cat_order)) - ((int) array_search($b->term_id , $cat_order));
});
If you're sure that all the categories are in your $cat_order array, you can forgo the integer casting.
P.S. If you're using PHP < 5.2, use a named function instead:
function sort_categories ($a, $b) {
return ((int) array_search($a->term_id , $cat_order)) - ((int) array_search($b->term_id , $cat_order));
}
usort($categories, 'sort_categories');

Related

Wordpress loop: custom number of posts and sort by date

I have tried to find a solution to something I need on the website (example here: https://www.baiweb.nl/). I have been looking for a way to show a custom number of posts per category AND sort them by date. I have managed to get a single post per category, but I can't seem to fix the rest. It sorts the posts itself by date now, but not all of them.
So, my questions are:
Is it possible to sort this loop, with all different categories, by date?
Is it possible to control the number of posts shown per category? This one is extra for me, not essential, but it would be nice.
Hope someone can help! Thanks a lot in advance for your time!
Here is my code used in the loop now:
<?php
$categories = get_categories();
$cats = array();
foreach($categories as $category) {
$cats[] = $category->name . ", ";
}
$exclude_posts = array();
foreach( $cats as $cat ) {
// build query argument
$query_args = array(
'category_name' => $cat,
'showposts' => 1,
'post_type' => 'post',
'post_status' => 'publish',
'orderby' => 'date',
'order' => 'DESC'
);
// exclude post that already have been fetched
// this would be useful if multiple category is assigned for same post
if( !empty($exclude_posts) )
$query_args['post__not_in'] = $exclude_posts;
// do query
$query = new WP_Query( $query_args );
// check if query have any post
if ( $query->have_posts() ) {
// start loop
while ( $query->have_posts() ) {
// set post global
$query->the_post();
// add current post id to exclusion array
$exclude_posts[] = get_the_ID();
?>
<article id="post-<?php the_ID(); ?>" <?php post_class('loop');?>>
<div class="corner"><span><?php foreach((get_the_category()) as $category){ echo $category->name.'<br> '; } ?></span></div>
<!-- thumbnail -->
<a href="<?php the_permalink(); ?>" title="<?php the_title(); ?>" class="image">
<?php
$thumb_id = get_post_thumbnail_id();
$thumb_url = wp_get_attachment_image_src($thumb_id,'medium', true);
if ( in_category('2') || in_category('32') ) {
echo '<div class="newstitle">' . the_title() . '</div>';
}
else {
if ( has_post_thumbnail()) {
echo "<div class='ctr-image test2' style='background-image: url(" . $thumb_url[0] . ")'></div>";
}
else {
echo '<div class="newstitle">' . the_title() . '</div>';
}
}
?>
</a>
<div class="content">
<span class="date"><?php the_time('j/m/Y'); ?></span>
<h3>
<a href="<?php the_permalink(); ?>" title="<?php the_title(); ?>">
<?php if ( in_category('2') || in_category('32') ) {}
else { echo the_title();} ?>
</a>
</h3>
<div class="text">
<?php html5wp_excerpt('html5wp_index'); // Build your custom callback length in functions.php ?>
</div>
</div>
</article>
<?php
// do something
}
} else {
// no posts found
}
// Restore original Post Data
wp_reset_postdata();
} ?>
You were close. Your categories foreach loop has to englobe everything. Then we do a simple loop but we specify what arguments to use depending on each categories.
Here is our final result.
<?php
$categories = get_categories(); // ... get all our categories
foreach( $categories as $category ) { // ... start foreach categories
if ( $category->name == 'Mercury' ) { // ... if our category name is 'Mercury'
$posts_per_page = 1; // ... 1 post per page if our category is named 'Mercury'
} else { // ... else, for all other categories
$posts_per_page = 3; // ... 3 posts per page
};
$args = array( // ... all our arguments
'posts_per_page' => $posts_per_page, // ... 1 or 3 posts per page depending on our categories
'post_type' => 'post',
'category_name' => $category->name,
'post_status' => 'publish',
'orderby' => 'date', // ... order by date
'order' => 'ASC', // ... most recent first
);
$query = new WP_Query( $args ); // .. start a new loop
if( $query->have_posts() ):
echo '<section>';
echo '<h1>' . $category->name . '</h1>'; // ... only display our section IF a post exist in the category
while( $query->have_posts() ): $query->the_post();
echo '<article>'; // ... our post template
the_title( '<h4>', '</h4>' );
echo '</article>';
endwhile;
echo '</section>';
endif;
wp_reset_postdata(); // ... After looping through a separate query, this function restores the $post global to the current post in the main query.
}; // ... end foreach categories
?>
Thank you so much for your quick and comprehensive answer! The part of the number of categories is working very well, however, the outcome is slightly different than I want. It may be that my question was not clear, apologies for that.
What you have already made beautiful is all the categories with posts that belong to it. What I want to achieve is that all messages are mixed up, sorted by date and, what was already done here, I can indicate how many posts are in per category. Is that even possible?
Some screenshotsof the outcome of your code:
This is what I am trying, except now I need to sort this by date:
This is the code slightly adjusted:
<?php
$categories = get_categories(); // ... get all our categories
foreach( $categories as $category ) { // ... start foreach categories
if ( $category->name == 'Mercury' ) { // ... if our category name is 'Mercury'
$posts_per_page = 1; // ... 1 post per page if our category is named 'Mercury'
} else { // ... else, for all other categories
$posts_per_page = 2; // ... 3 posts per page
};
$args = array( // ... all our arguments
'posts_per_page' => $posts_per_page, // ... 1 or 3 posts per page depending on our categories
'post_type' => 'post',
'category_name' => $category->name,
'post_status' => 'publish',
'orderby' => 'date', // ... order by date
'order' => 'ASC', // ... most recent first
);
$query = new WP_Query( $args ); // .. start a new loop
if( $query->have_posts() ):
// echo '<section>';
// echo '<h1>' . $category->name . '</h1>'; // ... only display our section IF a post exist in the category
while( $query->have_posts() ): $query->the_post();
echo '<article>'; // ... our post template
echo '<h1>' . $category->name . '</h1>';
the_time('j/m/Y');
the_title( '<h4>', '</h4>' );
echo '</article>';
endwhile;
// echo '</section>';
endif;
wp_reset_postdata(); // ... After looping through a separate query, this function restores the $post global to the current post in the main query.
}; // ... end foreach categories ?>
Hope this is clear, thanks again!

How to display only certain categories in Wordpress

I'm working in Wordpress and implemented some PHP to display all categories on a page (by a shortcode). By clicking on a category it links to a new page displaying all posts of that very category.
How do I display only certain categories, for instance by id and/or name of the cateogry?
One post has two categories (a : A & B or A & C). So one post a always has one category A, and one category B or C.
Here's my code:
function swerft_categories( ){
ob_start();
$categories = get_categories();
echo '<div class="swerft_cat">';
foreach($categories as $category) {
echo '<div class="swerft_cat_single col-lg-3 col-md-3 col-sm-6 col-xs-12">';
echo '<div class="swerft_cat_single_inner">';
$thim_group_custom_title_bg_img = get_term_meta( $category->term_id, 'thim_group_custom_title_bg_img', true );
if ($thim_group_custom_title_bg_img) {
$image_id = $thim_group_custom_title_bg_img['id'];
if ($image_id) {
$post_thumbnail_img = wp_get_attachment_image_src( $image_id, 'full' );
echo '<img src="' . $post_thumbnail_img[0] . '" alt="' . $category->name . '" />';
}
}
echo '<h5>'. $category->name .'</h5>';
echo '<p>'. $category->description . $category->count . '<span> Seminare </span>' . '</p>';
echo '</div>';
echo '</div>';
}
echo '</div>';
return ob_get_clean();
}
add_shortcode( 'swerft_categories', 'swerft_categories' );
I tried this in the first few lines for example with no success:
function swerft_categories($args){
ob_start();
$args = array('hide_empty'=> 1,
'name' => 'B');
$categories = get_categories($args);
1) I want only one certain relation to be displayed. Let's say: only the relation of a : A & B
2) I want the count to only show the amount of posts based on the relation above.
3) By clicking on a category based on this relation, I want only those posts to be displayed of course.
I was able to find a solution for the above mentioned problem together with a colleague. See the code below, I hope it may help someone maybe; and thanks for anyone considering this task though ;)
// Function to only show individual seminars after click on category on category-page
function swerft_filter_posts_open_individual_seminare( $query ) {
$offene_seminare = isset($_GET['offene_seminare']) ? boolval($_GET['offene_seminare']) : false;
$individual_seminars_category_id = 91;
if($query->is_category() && $query->is_main_query()) {
if ($offene_seminare) {
$query->set( 'category__not_in', $individual_seminars_category_id );
} else {
$query->set( 'category__in', $individual_seminars_category_id );
}
}
}
add_action( 'pre_get_posts', 'swerft_filter_posts_open_individual_seminare' );
// Function to only count individual seminars in overview
function swerft_count_individual_seminars_in_category($category_id) {
$individual_seminars_category_id = 91;
$query_args = array(
'post_type' => 'post',
'category__and' => array($individual_seminars_category_id, $category_id)
);
$query = new WP_Query( $query_args );
$count = $query->found_posts;
return $count;
}

WordPress: Show random 4 categories with 3 last posts

I am busy to build a row that will show randomly 4 categories with the category title and the 3 latest posts under it. But i am stuck how i can get the categories in random order because the 'orderby' is not working...
Can somewone help me with that?
The code i am using:
<?php
//for each category, show all posts
$cat_args = array(
'orderby' => 'rand',
'order' => 'ASC'
);
$limit = 4;
$counter = 0;
$categories = get_categories($cat_args);
foreach ($categories as $category):
if ($counter < $limit) {
$args = array(
'showposts' => 3,
'category__in' => array(
$category->term_id
),
'caller_get_posts' => 1
);
$posts = get_posts($args);
if ($posts) {
echo '<h3><a href="' . get_category_link($category->term_id) . '" title="' . sprintf(__("View all posts in %s"), $category->name) . '" ' . '>' . $category->name . '</a> </h3>';
foreach ($posts as $post) {
setup_postdata($post);
?>
<p><?php the_title(); ?></p>
<?php
} // foreach($posts
} // if ($posts
} // foreach($categories
?>
<?php
$counter++;
endforeach;
?>
Remove below code. This will only work with posts.
$cat_args = array(
'orderby' => 'rand',
'order' => 'ASC'
);
Use the code as below:
$categories = get_categories();
shuffle ($categories); // Just add shuffle and you will get random categories.
you can use this for get random cat :
$categories = get_the_category($my_query->post->ID);
$catCount = count($categories);
//select a random category id
$id = rand(0,$catCount-1);
//cat id
$catId = $categories[$id]->term_id;
and replace to lines like
if(is_array($cat)) {
$categories = get_the_category($my_query->post->ID);
$catCount = count($categories);
//select a random category id
$id = rand(0,$catCount-1);
//cat id
$catId = $categories[$id]->term_id;
} else {
$catId = $cat;
}

WP navigation post of a custom post type

I need to include in single.php a navigation buttons with previous and next post of the custom post type called 'works'.
I include this
<?php echo get_next_posts_link('Go to next post'); ?>
<?php echo get_previous_posts_link('Go to prev post');?>
or this
<?php previous_post_link( $taxonomy = 'works' ); ?>
But don´t show nothing or the navigation include all posts and pages. Only need pagination the post of this CUT like a carousel gallery, for example.
I think u search this one:
https://codex.wordpress.org/Pagination
A pagination for the last Posts of this Post Type.
U dosen't need a special "Menü" for this.
Try this
<?php
$term_list = wp_get_post_terms($post->ID, 'TAXONOMY', array("fields" => "slugs"));
if (empty($term_list[1])) {
print_r($term_list[0]);
$termo = $term_list[0];
} else {
print_r($term_list[1]);
$termo = $term_list[1];
}
// get_posts in same custom taxonomy
$postlist_args = array(
'posts_per_page' => -1,
'orderby' => 'menu_order title',
'order' => 'ASC',
'post_type' => 'CUSTOM-POST-TYPE',
'taxonomy'=>'TAXONOMY',
'term'=>$termo,
);
$postlist = get_posts( $postlist_args );
// get ids of posts retrieved from get_posts
$ids = array();
foreach ($postlist as $thepost) {
$ids[] = $thepost->ID;
}
// get and echo previous and next post in the same taxonomy
$thisindex = array_search($post->ID, $ids);
$previd = $ids[$thisindex-1];
$nextid = $ids[$thisindex+1];
if ( !empty($previd) ) {
echo '<a rel="prev" href="' . get_permalink($previd). '">previous</a>';
}
if ( !empty($nextid) ) {
echo '<a rel="next" href="' . get_permalink($nextid). '">next</a>';
}
?>
Good Luck.
Regards
If using the same category does not work, then you should try this. Add the tag "works" to the posts in your custom post-type. Then you can get the previous_ and next_post_link to this tag:
<?php previous_post_link( '%link', 'Previous in works', TRUE, ' ', 'post_tag' ); ?>
<?php next_post_link( '%link', 'Next in works', TRUE, ' ', 'post_tag' ); ?>

Wordpress: get & store category info

I'm wondering: is there any way I can load all the categories and store each one in a different array?
So i've got this code:
<?php
$cat_args = array('orderby' => 'name','order' => 'ASC');
$categories = get_categories($cat_args);
foreach($categories as $category) {
$args = array(
'showposts' => -1,
'category__in' => array($category->term_id),
'caller_get_posts' => 1
);
$posts = get_posts($args);
if ($posts) {
echo '<p>Category: <a href="' . get_category_link( $category->term_id ) . '" title="' . sprintf( __( "View all posts in %s" ), $category->name ) . '" ' . '>' . $category->name.'</a> </p> ';
foreach($posts as $post) {
setup_postdata($post);
?> <p><?php the_title(); ?></p> <?php
} // foreach($posts
} // if ($posts
} // foreach($categories
?>
I want to make it so that I can use it later like that (outside the loop):
<?php echo $category[0] -> name . $category[1] -> name . $category[2] -> name; ?>
If you just need an array of category names, you can alter your code as follows; (PLEASE NOTE:caller_get_posts and showposts has been depreciated a couple of years ago. They where replaced by ignore_sticky_posts and posts_per_page respectively)
<?php
$cat_args = array('orderby' => 'name','order' => 'ASC');
$categories = get_categories($cat_args);
$category_names = array();
foreach($categories as $category) {
$category_names[] = $category->name;
$args = array(
'posts_per_page' => -1,
'category__in' => array($category->term_id),
'ignore_sticky_posts' => 1
);
$posts = get_posts($args);
if ($posts) {
echo '<p>Category: <a href="' . get_category_link( $category->term_id ) . '" title="' . sprintf( __( "View all posts in %s" ), $category->name ) . '" ' . '>' . $category->name.'</a> </p> ';
foreach($posts as $post) {
setup_postdata($post);
?> <p><?php the_title(); ?></p> <?php
} // foreach($posts
} // if ($posts
} // foreach($categories
?>
$category_names will now hold an array of category names.
If you need to display a list of categories with posts below them, you should check out my post here on WPSE. Your method is very resource intensive and slow. My method is superfast, use transients, and at optimum does only 2 db queries in under 0.002 seconds
Note: You already have the data in this format in $categories variable.
So you can use anywhere like this
<?php echo $categories[0] -> name . $categories[1] -> name . $categories[2] -> name; ?>

Categories