Currently I'm using get_posts to get the 10 latest posts, but the problem is that I don't get all information. For example I can't access the post category or author.
I would like to use WP_Query with get_the_title(), get_the_post_thumbnail, get_permalink() etc. The results have to be stored into variables.
My setup:
$latest_posts = get_posts( array(
'category_name' => 'Allgemein',
'posts_per_page' => 10,
"orderby" => "date",
"order" => "DESC"
) );
// Post 1 -- Category: Allgemein
if ( isset( $latest_posts[0] ) ) { // array zero-based index.
// $post1_category = $latest_posts[0]->post_category;
$post1_date = $latest_posts[0]->post_date;
$post1_title = $latest_posts[0]->post_title;
// $post1_tags = $latest_posts[0]->post_tags;
$post1_author = $latest_posts[0]->post_author;
$post1_content = $latest_posts[0]->post_content;
$post1_thumbnail = $latest_posts[0]->get_the_post_thumbnail;
}
// Post 2 -- Category: Allgemein
if ( isset( $latest_posts[1] ) ) {
// $post2_category = $latest_posts[1]->post_category;
$post2_date = $latest_posts[1]->post_date;
$post2_title = $latest_posts[1]->post_title;
// $post2_tags = $latest_posts[1]->post_tags;
$post2_author = $latest_posts[1]->post_author;
$post2_content = $latest_posts[1]->post_content;
$post2_thumbnail = $latest_posts[1]->get_the_post_thumbnail;
}
Post3-10
....
And in my index.php:
<div class="title">
<?php echo $post1_title?>
</div>
To get the categories, use the function wp_get_post_categories:
$post1_category = wp_get_post_categories($latest_posts[0]->ID);
To get the tags, use the function wp_get_post_tags:
$post1_tags = wp_get_post_tags($latest_posts[0]->ID);
WordPress has more functions to retrieve the post data using the post ID. Follow:
Get the Title
Get the post thumbnail URL
Your variable $latest_posts[X] is a WP_Post Object, wich contains some data. See the full data list in the WP_Post Reference.
Related
I want to display in the article sidebar (in wordpress) a list of 5 recent articles from that category to which it belongs. I'm using the code below to (using a shortcode) show the 5 posts (from category 62 in this case). Is there a way to write this code in functions.php so that it is optimised, and I don't have to rewrite everything for each new category?
/**
* function to add recent posts widget
*/
function wpcat_postsbycategory_musculacao() {
// the query
$the_query = new WP_Query( array( 'cat' => '62', 'posts_per_page' => 5 ) );
// The Loop
if ( $the_query->have_posts() ) {
$string .= '<ul class="postsbytag widget_recent_entries">';
while ( $the_query->have_posts() ) {
$the_query->the_post();
if ( has_post_thumbnail() ) {
$string .= '<li>';
$string .= '' . get_the_post_thumbnail($post_id, array( 80, 80) ) . get_the_title() .'</li>';
} else {
// if no featured image is found
$string .= '<li>' . get_the_title() .'</li>';
}
}
} else {
// no posts found
}
$string .= '</ul>';
return $string;
/* Restore original Post Data */
wp_reset_postdata();
}
// Add a shortcode
add_shortcode('categoryposts-musculacao', 'wpcat_postsbycategory_musculacao');
/**
* function to change search widget placeholder
*/
function db_search_form_placeholder( $html ) {
$html = str_replace( 'placeholder="Pesquisar ', 'placeholder="Buscar ', $html );
return $html;
}
add_filter( 'get_search_form', 'db_search_form_placeholder' );
The complication here is that in WP a post can have multiple categories. You need to decide how to handle that - get from all categories, or if you only want to show posts from one category, how do you choose which?
I've given a few answers below depending on how you want to handle that.
1. Get posts in any of the categories of the current post
As posts can have multiple categories, you can get all of the ids and use this to query for posts that are in any of those categories:
// 1. get the categories for the current post
global $post;
$post_categories = get_the_category( $post->ID );
// 2. Create an array of the ids of all the categories for this post
$categoryids = array();
foreach ($post_categories as $category)
$categoryids[] = $category->term_id;
// 3. use the array of ids in your WP_Query to get posts in any of these categories
$the_query = new WP_Query( array( 'cat' => implode(",",$categoryids), 'posts_per_page' => 5 ) );
1a. Get posts in any of the categories but not their children
Note cat will include children of those category ids. If you want to include those exact categories only and not children, use category__in instead of cat:
$the_query = new WP_Query( array('category__in' => $categoryids, 'posts_per_page' => 5) );
2. Get posts that have all of the categories of the current post
If you want posts that have all the same categories as the current one, this is done in the same way as above, except we use category__and instead of cat (Note that this does not include children of those categories) :
$the_query = new WP_Query( array('category__in' => $categoryids, 'posts_per_page' => 5) );
3. If you know your post will only have one category
If you know you only have one category per post, then you can just use the first element from the category array:
// 1. Just use the id of the first category
$categoryid = $post_categories[0]->term_id;
$the_query = new WP_Query( array( 'cat' => $categoryid, 'posts_per_page' => 5 ) );
4. Pass the category into the shortcode
If you want to specify which category to show, you can pass the category id into the shortcode, letting you choose whichever category you want. (FYI you can also get it to work with slug instead of id, which might be a bit more user-friendly)
Your shortcode is currently used like this, I assume:
[categoryposts-musculacao]
We can change the function so you can pass the category like this:
[categoryposts-musculacao category=62]
Shortcode function can accept an $attributes argument that has the information or "attributes" we're adding to the shortcode, e.g. category. We use this to get the category passed in as a variable called $category and then just use it instead of the hardcoded value in the rest of your function.
// 1. include the $attributes argument
function wpcat_postsbycategory_musculacao( $attributes ) {
// 2. get the value passed in as category - this will save it into a variable called `$category`
extract( shortcode_atts( array(
'category' => ''
), $attributes ) );
// 3. if there is no category don't do anything (or sohw a message or whatever you want
if (!$category) return "";
// 4. Now just use your variable instead of the hardcoded value in the rest of the code
$the_query = new WP_Query( array( 'cat' => $category, 'posts_per_page' => 5 ) );
// do the rest of your stuff!
}
Reference: Wordpress Codex Shortcode API
4a. Pass the category into the shortcode by slug
If you want the category attribute in your shortcode to work with a slug instead of the id, you just need to change WP_Query to use category_name instead of cat:
$the_query = new WP_Query( array( 'category_name' => $category, 'posts_per_page' => 5 ) );
I want to have Wordpress post title in array.
I have my post titles in my custom post type as names of people with their surnames. I want to display my posts based alphabetically on their surnames and store it in an array. How do I do this in the loop?
You can retrieve the posts for your custom post type using WP_Query, and then run through each of them to get the titles.
// just get IDs rather than whole post object - more efficient
// as you only require the title
$post_ids = new WP_Query(array(
'post_type' => 'custom_post_type_name', // replace with CPT name
'fields' => 'ids',
'orderby' => 'meta_value',
'meta_key' => 'surname_field_name' // replace with custom field name
));
$post_titles = array();
// go through each of the retrieved ids and get the title
if ($post_ids->have_posts()):
foreach( $post_ids->posts as $id ):
// get the post title, and apply any filters which plugins may have added
// (get_the_title returns unfiltered value)
$post_titles[] = apply_filters('the_title', get_the_title($id));
endforeach;
endif;
Using WP_Query has the benefit that it does not alter the main loop on your page, and you can get the posts in the order that your require by using orderby along with the name of the custom field which contains the surname.
You can create an array outside the loop, then get the array filled up with the names, than sort the array.
<?php
// the array for the names
$name_array = array();
if ( have_posts() ) {
while ( have_posts() ) {
the_post();
$name_array[] = $post->title;
//
// Post Content here
//
} // end while
if ( sizeof( $name_array ) > 0 ) {
sort( $name_array );
} // end if for sizeof()
} // end if
?>
If you cannot create the array outside The Loop, than you may move it under if ( have_posts() ) {.
Important note: this solution only contains the names in your current loop, so if your query does not hold all the posts, or is offset / paged, etc. then the array will not get all the names you have in your custom post type. If you would like to have all the names in the array and your loop query does not hold all the posts, then you have to query again - just for the titles (names).
I have two different custom post types, portfolio and project.
On the single-project.php page, I want to display content where get_field('housetype') in project matches with the taxonomy of the portfolio. The content comes from the project custom post type.
So far I've managed to get all relevant information but I cant find a way to only display the result where there's a match between the housetype and the taxonomy.
I thinking that pushing the item in an array when it's a match and then using a foreach loop to display the content in a table. I just don't know how to do this..
Here's my code so far:
$args = array(
'post_type' => array( 'portfolio', 'project' ));
$my_query = new WP_Query( $args );
if( $my_query->have_posts()) {
while ($my_query->have_posts()) : $my_query->the_post();
//Returns All Term Items for "my_taxonomy"
$term_list_portfolio = wp_get_post_terms($post->ID, 'portfolio_category', array("fields" => "all"));
// Just get the category
$category = $term_list[0]->name;
// Get the house type
$houseType = get_field('hustyp');
$result = array($term_list[0]->name, get_field('hustyp'));
endwhile;
}
You would have to check with an if statement somewhere.
Something similar to this:
// Get the house type
$houseType = get_field('hustyp');
if($houseType == $term_list[0]->name){
//Here you could save your post object
//(that you declare before your while loop) to an array
//or render what you want directly
$posts[] = $post;
}
$result = array($term_list[0]->name, get_field('hustyp'));
So i am using ajax to filter and load posts into a container. I want to limit the amount of posts to 6 at a time and add a load more button underneath if there are more than 6 posts, but i don't want to add pages because i have a few containers on the same page that i'm using this same treatment for and my understanding is pages would add a /page-1 or something like that to the url (am i wrong?).
Either way, i just want to know how to check if there are more posts that fit this criteria so i can show the load more button, and then when the load more button fires how do i just load 6 more. Do i have to keep a page variable somewhere? or is there another smarter way.
Here is my query
function ajax_filter_get_posts( $category, $tag )
{
$category = $_POST['category'];
$tag = $_POST['tag'];
if($category)
{
$category_args = array(
'taxonomy' => 'category',
'field' => 'slug',
'terms' => $category
);
}
$args = array(
'posts_per_page' => 6,
'post_status' => 'publish',
'tag' => implode(",",$tag),
'tax_query' => array(
$category_args,
),
'category__in' => array(187,186,183,182,184),
);
$query = new WP_Query( $args );
if ( $query->have_posts() ) : while ( $query->have_posts() ) : $query->the_post();
$output = post_factory($post);
$result['response'][] = $output;
$result['status'] = 'success';
endwhile; else:
$result['response'] = '<h2>No posts found</h2>';
$result['status'] = '404';
endif;
$result = json_encode($result);
echo $result;
die();
}
I know this post is about a year old, but in case anyone else needs an answer, here's the solution I'm implementing. I'm using Ajax to pull in a wp_query from a PHP file. The output from that file replaces the content of a div on my page. This is only the relevant code, not my complete code.
On click of the load more button, I use jQuery to count the number of posts on the page and put that count into a variable. Posts have a unique class assigned to them.
current = $('.item').length;
I send the post count to the PHP file using Ajax.
$.get(functions_home.url, { offset: current }, function(data) {
$('.grid').html(data);
}
I pull the post count from jQuery into a variable in the PHP file, and then use that variable to set the wp_query "offset" in $args.
$offset = $_GET['offset'];
$args = array (
'offset' => $offset
);
Once the query ($query) runs, I use $query->found-posts to tell me the total number of relevant posts, and I put that in a variable.
$total = $query->found_posts;
I make a div in my PHP file and use the found posts variable so that it's populated with the total number of relevant posts. I use CSS to hide that div, so that it's never visible on the website.
<div id="total"><?php echo $total; ?></div>
#total {
display: none;
}
I use jQuery to find that div on the page, and get the text from it, which is the total number of relevant posts. I put that in a variable.
total = $('#total').text();
I use jQuery to check whether the number of posts on the page is equal to the total number of posts, and, if it is, I hide the load more button. For my particular situation, I check in both the initial Ajax load and the Ajax call that fires when the load more button is clicked.
current = $('.item').length;
total = $('#total').text();
if ( current == total ) {
$('.load-more').css({
display: 'none'
});
}
I don't know if this is the best solution, or even a good solution, but it's what I've figured out to do, and it's working for me so far.
WP_Query has a parameter max_num_posts which will tell you how many pages in total the query have.
Inside the callback function you can check if there any more pages left in a query and send the value in response. Than you will be able to hide/show "load more" button with JS function based on that value. You can something similar to this:
function ajax_filter_get_posts( $category, $tag, $paged = 1 )
{
$paged = $_POST['paged']; // Pass a number of a page that you want to retrieve. Default is page #1
$category = $_POST['category'];
$tag = $_POST['tag'];
if($category)
{
$category_args = array(
'taxonomy' => 'category',
'field' => 'slug',
'terms' => $category
);
}
$args = array(
'posts_per_page' => 6,
'paged' => $paged, // pass required page number to WP_Query
'post_status' => 'publish',
'tag' => implode(",",$tag),
'tax_query' => array(
$category_args,
),
'category__in' => array(187,186,183,182,184),
);
$query = new WP_Query( $args );
if ( $query->have_posts() ) : while ( $query->have_posts() ) : $query->the_post();
$output = post_factory($post);
$result['response'][] = $output;
$result['status'] = 'success';
endwhile; else:
$result['response'] = '<h2>No posts found</h2>';
$result['status'] = '404';
endif;
// Check if there are any more pages to query and pass the boolean value in response
$result['more_pages'] = ( ( $query->max_num_pages - $paged ) > 0 ) ? true : false;
$result = json_encode($result);
echo $result;
die();
}
I would like to put pagination on each single product page in WooCommerce so that a user can move between products in that category easier than having to go back out to the main category page every time.
I know it's possible to use the standard WordPress pagination links like…
<?php previous_post_link('« %link'); ?>
<?php next_post_link('%link »'); ?>
This works if I want to page through all products, but I only want to page through products that are within the category I'm in. Does anyone know how I can limit this so products outside this category aren't included?
I've tried using the in_same_term parameter as mentioned in the WordPress codex to get the links only showing if the next/prev product is in the same category, but it's returning an integer for some reason. Here's the code I'm using…
<?php next_post_link( '%link', '%title', TRUE, '' ); ?>
This returns nothing at all even though it follows the Codex structure. I've also tried…
<?php next_post_link( '%link %title', TRUE, '' ); ?>
And this is what I'm getting in return…
1 %title
I'm stumped where to go next.
Here is a function that I have recently written that also does the job and is quite flexible
THE IDEA:
You first need to get the current post id, which I get through get_queried_object_id(). The post ID will be used to retrieve:
The post terms the post belongs to with wp_get_post_terms(). To speed things up, only the ID's of the terms will be returned. The first ID will be used (you can modify the code here to decide which term will be used if a post have more than one term) and this will be used to retrieve all the posts which has this certain term
The post ID's of the posts that is directly adjacent to this post to determine and retrieve the next and previous post from this one
All the info above will be used in a tax_query with get_posts to retrieve all the posts that shares the term from the current post. In the function, the default taxonomy is category and the post_type is set to any to get all the posts that has this specific term
Again, to make the code faster and to safe on resources, we only going to get the post ID's as this is all that is needed
Now comes the important parts of the code. We now need to determine the following:
The current position of the current post in the returned array of post ID's from the custom get_posts query. The function used here is array_search
If there is a post before or after this post (next or previous posts, the definitions are the same as for the build in functions next_post_link() and previous_post_link()), get the ID's of these posts
Use the ID's with get_post to retrieve the next and previous post's titles from the current post
Lastly will be to return the links. I have set messages if the current post is either the first or last post in the array and there are no next or previous post. You can decide what you want to do here, and for all that matters, the rest of the code
To make the code even faster and more efficient, I have made use of the Transient API which you can read further on. I have also used the transition_post_status action hook to hook a function to delete these transients whenever the post status of a post change. This includes new posts being published, post being updated and post deleted/undeleted
THE CODE:
Here is the code. This goes into your functions.php
function get_post_link( $taxonomy = 'category', $post_type = [ 'any' ] ) {
$id = get_queried_object_id(); // Get the current post ID
$transient_id = 'post_number_' . md5( $id . $taxonomy . implode( ',', $post_type ) ); //Create a unique transient id
if ( false === ( $links = get_transient( $transient_id ) ) ) {
// Get the terms a post belongs to
$terms = wp_get_post_terms( $id, $taxonomy, array( 'fields' => 'ids' ) );
// Use a tax_query to get all posts from the given term
// Just retrieve the ids to speed up the query
$post_args = [
'post_type' => $post_type,
'fields' => 'ids',
'posts_per_page' => -1,
'tax_query' => [
[
'taxonomy' => $taxonomy,
'field' => 'term_id',
'terms' => $terms[0],
'include_children' => false,
],
],
];
// Get all the posts having the given term from all post types
$q = get_posts( $post_args );
//Get the current post position. Will be used to determine next/previous post
$current_post_position = array_search( $id, $q );
// Get the previous/older post ID
if ( array_key_exists( $current_post_position + 1 , $q ) ) {
$previous = $q[$current_post_position + 1];
}
// Get post title link to the previous post
if( isset( $previous ) ) {
$previous_post = get_post( $previous );
$previous_post_link = get_permalink( $previous );
$previous_title = '' . $previous_post->post_title . '</br>';
}
// Get the next/newer post ID
if ( array_key_exists( $current_post_position - 1 , $q ) ) {
$next = $q[$current_post_position - 1];
}
// Get post title link to the next post
if( isset( $next ) ) {
$next_post = get_post( $next );
$next_post_link = get_permalink( $next );
$next_title = '' . $next_post->post_title . '</br>';?><pre><?php var_dump($next_title); ?></pre><?php
}
// The returned post links
if( isset( $previous_title, $next_title ) ) {
$links = [
'previous_post' => $previous_title,
'next_post' => $next_title,
];
}elseif( !isset( $previous_title ) && $next_title ) {
$links = [
'previous_post' => 'You are currently viewing the newest post',
'next_post' => $next_title,
];
}elseif( $previous_title && !isset( $next_title ) ) {
$links = [
'previous_post' => $previous_title,
'next_post' => 'You are currently viewing the last post',
];
}
set_transient( $transient_id, $links, 7 * DAY_IN_SECONDS );
}
return (object)$links;
}
add_action( 'transition_post_status', function ( $new_status, $old_status, $post )
{
global $wpdb;
$wpdb->query( "DELETE FROM $wpdb->options WHERE `option_name` LIKE ('_transient%_post_number_%')" );
$wpdb->query( "DELETE FROM $wpdb->options WHERE `option_name` LIKE ('_transient_timeout%_post_number_%')" );
}, 10, 3 );
HOW TO USE:
You can now use the code as follows in you single.php. The default taxonomy is category and post type is any. If your custom taxonomy is called mytax, you can use the code like this
if( function_exists( 'get_post_link' ) ) {
$post_links = get_post_link( 'mytax' );
echo $post_links->previous_post . '</br>' . $post_links->next_post;
}