I'm using a custom post type to hold products, each product holds a name via a custom field. When I display the product via its singular template it would be nice to have a next & previous link to go through those products, but it should go through them in order of their name. Currently that’s not possible as they would be ordered by their publishing dates.
So I added the following code in functions.php, but it's not working, I don't know if this has to be made in a different way:
if(is_singular('products')) {
add_filter('get_previous_post_join', 'rt_post_join');
add_filter('get_next_post_join', 'rt_post_join');
add_filter('get_previous_post_where', 'rt_prev_post_where');
add_filter('get_next_post_where', 'rt_next_post_where');
add_filter('get_previous_post_sort', 'rt_prev_post_sort');
add_filter('get_next_post_sort', 'rt_next_post_sort');
}
function rt_post_join($join, $isc, $ec) {
global $wpdb;
$join = " INNER JOIN $wpdb->postmeta AS pm ON pm.post_id = p.ID";
return $join;
}
function rt_prev_post_where($w) {
global $wpdb, $post;
$prd = get_post_meta($post->ID, 'data_product_name_product', true);
$w = $wpdb->prepare(" WHERE pm.meta_key = 'data_product_name_product' AND pm.meta_value < '$prd' AND p.post_type = 'products' AND p.post_status = 'publish'");
return $w;
}
function rt_next_post_where($w) {
global $wpdb, $post;
$prd = get_post_meta($post->ID, 'data_product_name_product', true);
$w = $wpdb->prepare(" WHERE pm.meta_key = 'data_product_name_product' AND pm.meta_value > '$prd' AND p.post_type = 'products' AND p.post_status = 'publish'");
return $w;
}
function rt_prev_post_sort($o) {
$o = "ORDER BY pm.meta_value DESC LIMIT 1";
return $o;
}
function rt_next_post_sort($o) {
$o = "ORDER BY pm.meta_value ASC LIMIT 1";
return $o;
}
And in my single page of products (single-products.php) I added the following code to display the pagination links:
<?php next_post_link('%link', 'Next product'); ?>
<?php previous_post_link('%link','Previous product'); ?>
Thanks.
What you actually need is a custom Query. You can try this (not tested tho):
Place this in your functions.php:
function getProductsQuery() {
return new WP_Query(array(
'posts_per_page' => 10,
'post_type' => 'product',
'orderby' => 'title',
'order' => 'ASC'
));
}
Then, replace your loop with the following:
<?php $products = getProductsQuery(); ?>
<?php while($products->have_posts()): $products->the_post(); ?>
<h2><?php the_title(); ?></h2>
(...)
<?php endwhile; ?>
Finally I solved it!
I just used the plugin Next/Previous Post Link Plus for WordPress and added the following code in my single page of products (single-products.php):
<?php next_post_link_plus( array(
'order_by' => 'custom',
'meta_key' => 'data_product_name_product',
'link' => 'Next product',
'format' => '%link'
)); ?>
<?php previous_post_link_plus( array(
'order_by' => 'custom',
'meta_key' => 'data_product_name_product',
'link' => 'Previous product',
'format' => '%link'
)); ?>
Related
I need to show a counter within my single page post (I use it as a shortcode).
I have a custom post type (slug = 'portfolio') that has different categories.
When I am in the single post, I want to display a counter such as "n/tot" where
n = number of post (first post within the category = 1; second post= 2 etc)
tot = total number of posts within that category
I found the way to show the total number of posts, but not within a category
add_shortcode( 'tot_posts', 'number_factsheets' );
function number_factsheets () {
$total = wp_count_posts('portfolio')->publish;
$output = '<div class="count">';
$output .= $total;
$output .='</div>';
return $output;
}
Is it possible to obtain the data above when I am in single page post? And how?
WORKING CODE FOR RETRIEVING NUMBER OF SINGLE CUSTOM POST TYPE OVER TOTAL NUMBER OF CPT WITHIN A SPECIFIC CATEGORY
add_shortcode('post-counter', 'get_current_post_num');
function get_current_post_num() {
$url = $_SERVER['REQUEST_URI'];
$curr_post_id = url_to_postid( "https://sharkrayareas.org".$url ); //Too early for $post object
$taxonomy = 'portfolio_entries';
$term_objs = get_the_terms( $curr_post_id->ID, $taxonomy );
foreach ($term_objs as $term_obj)
$term_ids = $term_obj->term_id; // get the id from the WP_Term object
$args = array(
'post_type' => 'portfolio',
'post_status' => 'publish',
'tax_query' => array(
array(
'taxonomy' => 'portfolio_entries',
'terms' => $term_ids,
),
),
'order'=> 'ASC',
'posts_per_page' => -1
);
$portfolio_posts = new WP_Query($args);
if ($portfolio_posts->have_posts()):
echo 'true';
$total_posts = $portfolio_posts->found_posts;
$num = 1;
while ($portfolio_posts->have_posts()) : $portfolio_posts->the_post();
$post_id = get_the_ID();
if ($post_id === $curr_post_id) {
$output= '<div class="count">'. $num . '/' . $total_posts .'</div>';
} else {
$num++;
}
endwhile;
endif;
return $output;
}
I recommend going about that by looping through the posts and checking whether the the page you are on is that point in the loop. I'm including an example that prints it on-page.
add_action('init', 'get_current_post_num');
function get_current_post_num() {
$url = $_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'];
$curr_post_id = url_to_postid( "https://".$url ); //Too early for $post object so get $curr_post_id from url_to_postid
$args = array(
'post_type' => 'portfolio',
'post_status' => 'publish',
'posts_per_page' => -1
);
$portfolio_posts = new WP_Query($args);
if ($portfolio_posts->have_posts()):
$total_posts = $portfolio_posts->found_posts;
$num = 1;
while ($portfolio_posts->have_posts()) : $portfolio_posts->the_post();
$post_id = get_the_ID();
if ($post_id === $curr_post_id) {
echo $num . '/' . $total_posts;
} else {
$num++;
}
endwhile;
endif;
}
I am trying to make a shortcode that should pull up the most recent comment (only one), Comment author name and thumbnail of the blog post on which this comment is published no matter if the blog post is the most recent or the older one. The comment should be the most recent one.
I made the code but it is not pulling the most recent comment.
function ct_comment_block(){
$query = new WP_Query(
array(
'post_type' => 'post',
'post_status' => 'publish',
'posts_per_page' => 1,
'tax_query' => array(
'taxonomy' => 'calendar_category',
'field' => 'slug'
),
'order' => 'ASC',
'orderby' => 'menu_order'
)
);
$str = '';
$thumb_id = get_post_thumbnail_id();
$thumb_url_array = wp_get_attachment_image_src($thumb_id, 'thumbnail-size', true);`$thumb_url = $thumb_url_array[0];
while ($query->have_posts()):
$query->the_post();
$str .= '<div class="comment-main">
<div class="comment-image-wrapper">'.get_the_post_thumbnail().'</div>
<div class="comment-wrapper">
<h3>'.comment_sender().'</h3>
<h5>Traveler Hobbyist</h5>
<p>'.real_body().'</p>
</div>';
$str .= '</div>';
endwhile;
return $str;
}
add_shortcode('show_comment' , 'ct_comment_block');
I have written most of the my anser in the code comments.
But I would use a $wpdb query to fetch the newest comment, get the id of the assosiated post and work from there.
Hopefully this makes sense to you.
<?php
add_shortcode('show_comment' , 'ct_comment_block');
function ct_comment_block(){
if(!is_admin()){
global $wpdb;
$query = "SELECT * from $wpdb->comments WHERE comment_approved= '1' ORDER BY comment_date DESC LIMIT 0 ,1"; // This shows the newest comment
$comments = $wpdb->get_results($query);
$strToReturn = '';
if ($comments) {
$strToReturn .= '<div class="someSortOfWrappingClass">';
foreach ($comments as $comment) {
//Use $comment->comment_post_ID for the post_id like so
$link = get_permalink($comment->comment_post_ID);
//but you can check what else is inside $comment - like $comment->comment_author_email etc.
//Simply gather your html here
} //End of foreach
$strToReturn .= '</div>';
} //End of IF
return $strToReturn;
} else {
return;
}
}
Try it may help you for get most recent comments
$recentcomments = get_comments( array(
'number' => 10, // fetch number of comments.
'status' => 'approve', // status approved comments.
'post_status' => 'publish' // post status published comments.
) );
if ( $recentcomments ) {
foreach ( (array) $recentcomments as $comment ) {
echo '' . get_the_title( $comment->comment_post_ID ) . '';
}
}
I have a piece of code for displaying related posts by the post tag, but I don't know how to call posts in theme,
so I have this code which I have to put in my theme functions file:
function exe_get_related_posts_by_common_terms( $post_id, $number_posts = 0, $taxonomy = 'post_tag', $post_type = 'post' ) {
global $wpdb;
$post_id = (int) $post_id;
$number_posts = (int) $number_posts;
$limit = $number_posts > 0 ? ' LIMIT ' . $number_posts : '';
$related_posts_records = $wpdb->get_results(
$wpdb->prepare(
"SELECT tr.object_id, count( tr.term_taxonomy_id ) AS common_tax_count
FROM {$wpdb->term_relationships} AS tr
INNER JOIN {$wpdb->term_relationships} AS tr2 ON tr.term_taxonomy_id = tr2.term_taxonomy_id
INNER JOIN {$wpdb->term_taxonomy} as tt ON tt.term_taxonomy_id = tr2.term_taxonomy_id
INNER JOIN {$wpdb->posts} as p ON p.ID = tr.object_id
WHERE
tr2.object_id = %d
AND tt.taxonomy = %s
AND p.post_type = %s
GROUP BY tr.object_id
HAVING tr.object_id != %d
ORDER BY common_tax_count DESC" . $limit,
$post_id, $taxonomy, $post_type, $post_id
)
);
if ( count( $related_posts_records ) === 0 )
return false;
$related_posts = array();
foreach( $related_posts_records as $record )
$related_posts[] = array(
'post_id' => (int) $record->object_id,
'common_tax_count' => $record->common_tax_count
);
return $related_posts;
}
and now I want to call 10 posts from the above code in my single.php that can show post title and post thumbnail with the link to every post.
try something like that:
$query = new WP_Query(array(
'post_status' => 'publish',
'post_type' => 'your-posttype', // or 'any'
'tag_slug__in' => 'your-tag',
'order' => 'DESC',
'posts_per_page' => 10
));
Then you will get latest 10 posts
This function is very useful, people continually looking for ways to get related posts
What this function does:
The code you are using is a working function that is returning an array of posts related to current post depending on common terms.
How this function works:
You can call the function from your single.php file and as input you have to provide 4 info. The current post ID, the number of related posts to return, the post_term to filter the related posts (post_tag) and at last the post_type.
Example function call: exe_get_related_posts_by_common_terms(get_the_ID(), 10, 'post_tag', 'post')
The above example will return 10 post ids as array based on current post ID and the tag
- Returning the post array and loop through ID's
Now we only need a custom wp_query in order to loop through the array and format the output.
Example wp_query:
$args = array(
'post_type' => 'post',
'post__in' => $related_post
);
// The Query
$related_query = new WP_Query( $args );
Result:
Full working example returning the post titles in an unordered list:
<?php
$cpid = get_the_ID(); // get current post id
$related_posts = exe_get_related_posts_by_common_terms($cpid, 10, 'post_tag', 'post');
$posts_array = array_column($related_posts, 'post_id'); // new single dimension array with the ID's
$args = array(
'post_type' => 'post',
'post__in' => $posts_array
);
// The Query
$related_query = new WP_Query( $args );
if ($related_query->have_posts()) : ?>
<ul>
<?php while ($related_query->have_posts()) : $related_query->the_post(); ?>
<li><?php the_title(); ?></li>
<?php endwhile; ?>
</ul>
<?php endif; ?>
You can now set the look and fill as you like
I have a custom post type of 'location'. I then have children pages for each of the pages for that cpt. so it looks something like this, "www.example.com/location/location-name/child-page/", each child page is using a post template of "location-product-services.php". So what I am trying to do is exclude from the search results the children of this cpt.
I am trying to do it by checking the meta data to see if it is using that template. I just cant seem to get it working. Any help would be great.
This is what I currently have -
// Exclude local product and services pages from search result.
function location_subpages_exclude_search( $query ) {
if ( is_search() && !is_admin()) {
$query->set('meta_query',
array(
'key' => '_wp_page_template',
'value' => 'location-product-services.php',
'compare' => '!='
)
);
}
}
add_action('pre_get_posts', 'location_subpages_exclude_search');
Thanks in advance.
First, I pretty much exclusively use the Relevanssi plugin any time I want to modify search. But to search programmatically, I think this is what you're after:
$taxonomy = 'location';
$terms = get_terms($taxonomy, array( 'parent' => 0, 'search' => $query ) );
if ( $terms && !is_wp_error( $terms ) ) :
?>
<ul>
<?php foreach ( $terms as $term ) { ?>
<li><?php echo $term->name; ?></li>
<?php } ?>
</ul>
<?php endif;?>
Use the function get_terms to search your CPT, the 'search' is your $query (you might consider wrapping the search string with the SQL wildcard '%') and 'parent'=>0 returns only the top level.
I figured it out.
First I got all parent pages of my post type, used get_pages() grab them all.
Looped through each of the parent pages and ran another get_pages() for children of that parent.
function SearchFilter($query) {
if ($query->is_search) {
$args = array(
'hierarchical' => 0,
'post_type' => 'location',
'parent' => 0, //returns all top level pages
'post_per_page' => -1
);
$parents = get_pages($args);
$excludes = array();
foreach($parents as $parent) :
$args = array(
'post_type' => 'location',
'child_of' => $parent->ID,
'post_per_page' => -1
);
$children = get_pages($args);
foreach($children as $child):
array_push($excludes, $child->ID);
endforeach;
endforeach;
$query->set('post__not_in', $excludes);
}
return $query;
}
add_filter('pre_get_posts','SearchFilter');
I wanted to print tag list for my particular post type page. I used every function to fetch tags. but it is giving me all the tag list including used in other posts types.
<!-- begin custom related loop, isa -->
<?php
// get the custom post type's taxonomy terms
$custom_taxterms = wp_get_object_terms( $post->ID, 'your_taxonomy', array('fields' => 'ids') );
// arguments
$args = array(
'post_type' => 'your_custom_post_type',
'post_status' => 'publish',
'posts_per_page' => 3, // you may edit this number
'orderby' => 'rand',
'tax_query' => array(
array(
'taxonomy' => 'your_taxonomy',
'field' => 'id',
'terms' => $custom_taxterms
)
),
'post__not_in' => array ($post->ID),
);
$related_items = new WP_Query( $args );
// loop over query
if ($related_items->have_posts()) :
echo '<ul>';
while ( $related_items->have_posts() ) : $related_items->the_post();
?>
<li><?php the_title(); ?></li>
<?php
endwhile;
echo '</ul>';
endif;
// Reset Post Data
wp_reset_postdata();
?>
For creating filter type of widget. this must be required to fetch tag list as per the post types.
for that, I created one generic function by you can list tags or any taxonomy list as per the post type.
function get_terms_by_post_type( $taxo_term, $post_types ) {
global $wpdb;
$query = $wpdb->prepare(
"SELECT term.*, COUNT(*) from $wpdb->terms AS term
INNER JOIN $wpdb->term_taxonomy AS texo ON term.term_id = texo.term_id
INNER JOIN $wpdb->term_relationships AS tr ON tr.term_taxonomy_id = texo.term_taxonomy_id
INNER JOIN $wpdb->posts AS post ON post.ID = tr.object_id
WHERE post.post_type IN('%s') AND texo.taxonomy IN('%s')
GROUP BY term.term_id",
join( "', '", $post_types ),
join( "', '", $taxo_term)
);
$results = $wpdb->get_results( $query );
return $results;
}
Call this Function and pass taxonomy term and post type. it will give you an array of tags.