Hi I have created my own custom post type within Wordpress to contain projects that i can call via my theme files.
I am new to creating my own themes. I currently am using the following code in my single.php file to call in related articles based on the category of the blog post.
<?php
// Default arguments
$args = array(
'posts_per_page' => 3, // How many items to display
'post__not_in' => array( get_the_ID() ), // Exclude current post
'no_found_rows' => true, // We don't ned pagination so this speeds up the query
);
// Check for current post category and add tax_query to the query arguments
$cats = wp_get_post_terms( get_the_ID(), 'category' );
$cats_ids = array();
foreach( $cats as $wpex_related_cat ) {
$cats_ids[] = $wpex_related_cat->term_id;
}
if ( ! empty( $cats_ids ) ) {
$args['category__in'] = $cats_ids;
}
// Query posts
$wpex_query = new wp_query( $args );
// Loop through posts
foreach( $wpex_query->posts as $post ) : setup_postdata( $post ); ?>
<div class="col-md-4 related-post">
<?php the_post_thumbnail('large'); ?>
<?php the_title(); ?>
</div>
<?php
// End loop
endforeach;
// Reset post data
wp_reset_postdata(); ?>
In my new post type "projects" i would like to call in related projects. Which im assuming would be very similar code except i need to stop it looking for posts and instead look for my projects.
Here is my code for new post type:
// Projects
add_action( 'init', 'create_post_type' );
add_post_type_support( 'bw_projects', 'thumbnail' );
add_post_type_support( 'bw_projects', 'custom-fields' );
function create_post_type() {
register_post_type( 'bw_projects',
array(
'labels' => array(
'name' => __( 'Projects' ),
'singular_name' => __( 'Projects' )
),
'public' => true,
'has_archive' => true,
'taxonomies' => array( 'category','post_tag'),
)
);
}
What would i need to change in my first code snippet in order to look for bw_projects and not look for 'posts' anymore. I tried playing around and changing certain lines myself but i caused more issues and stopped the page loading. Is this even right i can use the same code, slightly altered or would i need something completely different?
Thanks in advance.
You can get any post type that you require using get_posts();
<?php $args = array(
'posts_per_page' => 5,
'offset' => 0,
'category' => '',
'category_name' => '',
'orderby' => 'date',
'order' => 'DESC',
'include' => '',
'exclude' => '',
'meta_key' => '',
'meta_value' => '',
'post_type' => 'projects',
'post_mime_type' => '',
'post_parent' => '',
'author' => '',
'author_name' => '',
'post_status' => 'publish',
'suppress_filters' => true
);
$posts_array = get_posts( $args ); ?>
Simply set the 'post_type' argument to that of you custom post type, to get only these posts. You can also set the number of post, and filter by category etc.
You can find more info in the codex.
Alternatively, if you wanted to keep something similar to your existing code you could try using 'pre_get_posts' to filter the query to just your projects. However you'd need to remember to add / remove this filter so it only operates on the queries that need it.
To display the posts you can use a simple foreach to churn them out. You#d obviously want to do some sort of styling to get the layout correct:
$args = array("posts_per_page" => 10, "orderby" => "comment_count");
$posts_array = get_posts($args);
foreach($posts_array as $post)
{
echo "<h1>" . $post->post_title . "</h1><br>";
echo "<p>" . $post->post_content . "</p><br>";
}
Or a really concise way of doing all of the above would be something like:
$args = array("posts_per_page" => 5, "post_type" => "projects");
$posts_array = get_posts($args);
foreach($posts_array as $post)
{
echo "<h1>" . $post->post_title . "</h1><br>";
echo "<p>" . $post->post_content . "</p><br>";
}
Related
I'm trying to create a custom shortcode in Wordpress that will let me place an attribute to specify a category and query within a custom post type called "case_studies". The taxonomy itself is called "case_study_categories" and I've set the default to be "furniture-interior", as you can see.
What I need is for the shortcode to look something like this:
[get_project_gallery order="ASC" tax_query="flooring"]
Ideally, the shortcode attribute I've placed would override the default of "furniture-interior" and instead use "flooring" to display the appropriate posts. Actually, I would think I don't even really need a default defined at all (so it would just get all the case_studies posts if no attribute is specified) but I can't get that to work either.
BTW, the attribute for order works exactly the way I would want - it overrides the defined default. I just can't figure out how to get this done with the $tax_query.
Any help on this would be very much appreciated. Thanks in advance all!
Here's my code:
function project_gallery_function($atts, $content = null) {
extract(shortcode_atts(array(
'order' => 'DESC',
'orderby' => 'date',
'tax_query' => array(
array(
'taxonomy' => 'case_study_categories',
'field' => 'slug',
'terms' => 'furniture-interior'
)
)
), $atts));
$args = array(
'post_type' => 'case_studies',
'post_status' => 'publish',
'posts_per_page' => '4',
'order' => $order,
'orderby' => $orderby,
'tax_query' => array($tax_query)
);
// The Query
$the_query = new WP_Query( $args );
// The Loop
if ( $the_query->have_posts() ) {
echo '<aside class="grid-gallery four-col grid-gap-4">';
while ( $the_query->have_posts() ) {
$the_query->the_post();
$gallery_thumb = get_the_post_thumbnail_url( $page->ID, 'thumbnail' );
echo '<img src="'. $gallery_thumb .'" alt="" />';
}
echo '</aside>';
}
/* Restore original Post Data */
wp_reset_postdata();
}
add_shortcode( 'get_project_gallery', 'project_gallery_function' );
You shouldn't be worrying about the whole entire tax_query unless you plan on actually redoing the whole tax_query. You should consider changing it to just using $terms instead, since that's the only part you're replacing with the shortcode (you don't need to rebuild the whole array).
Secondly, make sure your code is normalized with your spacing and indentation - future you appreciates the forethought!
Lastly, you could consider passing even more variables to the array to make it a bit more extensible - $posts_per_page, $taxonomy etc.
function project_gallery_function( $atts, $content = null ){
extract( shortcode_atts( array(
'terms' => 'furniture-interior',
'field' => 'slug',
'order' => 'DESC',
'orderby' => 'date',
'taxonomy' => 'case_study_categories',
'post_type' => 'case_studies',
'posts_per_page' => 4,
), $atts ) );
$tax_query = array(
array(
'taxonomy' => $taxonomy,
'field' => $field,
'terms' => explode(',', preg_replace('/\s+/', '', $terms)), // Force to array, allowing comma sep values
)
);
$args = array(
'post_type' => $post_type,
'post_status' => 'publish',
'posts_per_page' => $posts_per_page,
'order' => $order,
'orderby' => $orderby,
'tax_query' => array( $tax_query )
);
// The Query
$the_query = new WP_Query( $args );
// The Loop
if( $the_query->have_posts() ){
echo '<aside class="grid-gallery four-col grid-gap-4">';
while( $the_query->have_posts() ){
$the_query->the_post();
if( $gallery_thumb = get_the_post_thumbnail_url( $page->ID, 'thumbnail' ) ){
printf( '<img src="%s" alt="" />', get_the_permalink(), $gallery_thumb );
}
}
echo '</aside>';
}
/* Restore original Post Data */
wp_reset_postdata();
}
add_shortcode( 'get_project_gallery', 'project_gallery_function' );
A few other notes, get_the_post_thumbnail_url() returns a falsey value if it doesn't exist, so you should wrap that in an if statement incase the image can't be found for some reason (corrupted, removed, forgot to add, etc). Also you have a $page->ID variable in get_the_post_thumbnail_url() - but don't seem to have a global $page in the function? Make sure that's the variable you want to use there.
Using code like what I've provided will let you do what you want, [get_project_gallery order="ASC" terms="flooring"], or even add multiple [get_project_gallery order="ASC" terms="flooring,something-else,a-third-thing"] - just match up the shortcode attributes with the parameter you want to override: [get_project_gallery order="ASC" terms="flooring,something-else,a-third-thing" posts_per_page="15"]
I'm working on a short code for loop through parents ID and display all child page, but I'm not quite sure how to make the loop and make it more custom.
Here's my code:
add_shortcode( 'home-page-listing', 'get_list' );
function get_list( $atts ) {
ob_start();
$atts = shortcode_atts( array(
'ids' => ''
), $atts );
if($atts['ids']!='')
{
$id_array = explode(',',$atts['ids']);
$homePages = new WP_Query( array(
'post_type' => 'page',
'post__in'=>$id_array,
'order' => 'ASC',
'orderby' => 'post__in',
'posts_per_page' => -1
) );
if ($homePages->have_posts()){?>
<div class="">
<?php while ( $homePages->have_posts() ) : $homePages->the_post(); ?>
//here's html template code
<?php endwhile;
wp_reset_postdata(); ?>
</div>
}
}
}
Right now I can use [home-page-listing id=1,2,3,4] to display all select page ID, but I would like to make like this:
[home-page-listing parentID=4]
loop through all child page and display to the font, instead go check all the page id to display.
Thanks!
it's simple used post_parent Arguments of WP_Query. Please check below example
$homePages = new WP_Query( array(
'post_type' => 'page',
'post_parent'=>$parentID,
'order' => 'ASC',
'orderby' => 'parent',
'posts_per_page' => -1
) );
For more information of WP_Query click here
I want to get 3 featured products in the header of the site. But my query keeps returning unlimited number of results.
I've been looking online for a solution and came across answers that all answer saying the same thing in terms of the query. What could I be doing wrong?
$meta_query = WC()->query->get_meta_query();
$tax_query = WC()->query->get_tax_query();
$tax_query[] = array(
'taxonomy' => 'product_visibility',
'field' => 'name',
'terms' => 'featured',
'operator' => 'IN',
);
$args = array(
'post_type' => 'product',
'post_status' => 'publish',
'posts_per_page' => 2,
'meta_query' => $meta_query,
'tax_query' => $tax_query,
);
$featured_query = new WP_Query( $args );
if ($featured_query->have_posts()) {
while ($featured_query->have_posts()) :
$featured_query->the_post();
$product = get_product( $featured_query->post->ID );
echo $product->title; echo "test";
// Product info here
endwhile;
}
wp_reset_query();
The following query returned 20 results. The code was placed in header.php. Using woocommerce 3.x.
First your code is a bit outdated, since Woocommerce 3, as get_product() need to be replaced with wc_get_product() and $product->title; by $product->get_title();…
Once done your code works and you will get 3 featured products:
$meta_query = WC()->query->get_meta_query();
$tax_query = WC()->query->get_tax_query();
$tax_query[] = array(
'taxonomy' => 'product_visibility',
'field' => 'name',
'terms' => 'featured',
'operator' => 'IN',
);
$featured = new WP_Query( array(
'post_type' => 'product',
'post_status' => 'publish',
'posts_per_page' => 3, // <== <== <== 3 products
'meta_query' => $meta_query,
'tax_query' => $tax_query,
) );
// Get the products count in the query
echo '<p>Featured products count: ' .$featured->post_count . '</p>';
if ($featured->have_posts()) : while ($featured->have_posts()) :
$featured->the_post();
$product = wc_get_product( $featured->post->ID );
echo $product->get_title() . '<br>';
// Product info here
endwhile; endif;
wp_reset_postdata();
It should work for you as I have tested successfully this code on header.php file…
As before Woocommerce 3, the "featured products" where handled by post meta data (a meta query), you may need to update product terms count going to Woocommerce settings > status > tools. In "Term counts" section click on "Recount terms".
You should be using wp_reset_postdata() instead of wp_reset_query() since WP_query doesn't overwrite the main query.
If that doesn't solve your issue, make sure any other custom loops use the appropriate reset, and/or try renaming the variable $featured_query if you're using it elsewhere - it may be inheriting posts from a previous loop.
You could also try adding the 'nopaging' => true and 'ignore_sticky_posts' => true arguments
I hate to suggest it, but if you can't figure out why it's returning 20 posts instead of 2, you could just break your while loop with a counter:
if ($featured_query->have_posts()) {
$counter = 0;
while ($featured_query->have_posts()) : $featured_query->the_post();
/* Do post stuff here */
$counter++;
if( $counter == 2 ) break;
endwhile;
}
Please, help me with the matter discussed below:
I have registered this shortcode:
[category_post title="world news" category="world news" link="#"]
to call different categories. But the problem is when I post and select a single category, the post is shown in all category. But, I don't want this. I want the post to show only in that category that has been mentioned in the short-code. Can anyone help me to solve this problem?
Please, have a look at the picture and also I have given u the function here:
/* Register shortcode for querying custom category post *********/
function category_post_shortcode($atts){
extract( shortcode_atts( array(
'title' => '',
'link' => '',
'category' => '',
), $atts, 'category_post' ) );
$q = new WP_Query(
array( 'category' => $category, 'posts_per_page' => '4', 'post_type' => 'post')
);
$list = '<div class="latest_from_category"><h2 class="latest_frm_cat_title">'.$title.'</h2> more';
while($q->have_posts()) : $q->the_post();
//get the ID of your post in the loop
$id = get_the_ID();
$post_excerpt = get_post_meta($id, 'post_excerpt', true);
$post_thumbnail= get_the_post_thumbnail( $post->ID, 'post-thumbnail' );
$list .= '
<div class="single_cate_post floatleft">
'.$post_thumbnail.'
<h3>'.get_the_title().'</h3>
<p>'.$post_excerpt.'</p>
বিস্তারিত
</div>
';
endwhile;
$list.= '</div>';
wp_reset_query();
return $list;
}
add_shortcode('category_post', 'category_post_shortcode')
The category parameter for WP_Query expects the category ID - to query by name, use category_name:
$q = new WP_Query(
array( 'category_name' => $category, 'posts_per_page' => '4', 'post_type' => 'post')
);
http://codex.wordpress.org/Class_Reference/WP_Query#Category_Parameters
When producing a front page of a website and trying to grab five excerpts from the wordpress database it produces the excerpt, no problem, but it completely ignores my the_title, get_the_id and the_date:
foreach( $post as $posts) : setup_postdata($posts);
echo "<hr><h1>" . the_title( false, false, false ) . "</h1>";
echo the_excerpt( ) . "<br />";
echo "<a href='./index.php?p=" . get_the_ID( ) . "'><font color='white'>Read More...</font></a><br />";
echo "Published on: " . the_date( false, false, false, false );
endforeach;
Which produces the output:
http://i.stack.imgur.com/JNkxh.png
And as such, the 'Read More...' is directed to './index.php?p='
I have defined the get_posts statement as follows:
$args = array(
'posts_per_page' => 5,
'numberposts' => 5,
'offset' => 0,
'category' => $c,
'order_by' => 'post_date',
'order' => 'DESC',
'include' => '',
'exclude' => '',
'meta_key' => '',
'meta_value' => '',
'post_type' => 'post',
'post_mime_type' => '',
'post_parent' => '',
'post_status' => 'publish',
'suppress_filters' => true );
$post = get_posts( $args );
Any ideas on what went wrong would be much appreciated.
I think the problem lies with setup_postdata function.
Quote from setup_postdata Codex Page:
Important: You must make use the global $post variable to pass the
post details into this function, otherwise functions like the_title()
don't work properly...
Example from that Codex page:
global $post;
// Assign your post details to $post (& not any other variable name!!!!)
$post = $post_object;
setup_postdata( $post );
...
So try renaming $post to $mypost and then use exact $post variable in the setup_postdata() like this:
foreach( $mypost as $post) : setup_postdata($post);