Is there a function in wordpress to iterate through all posts and discard posts with same name? E.g. I have several posts named "Banana" and I need just one post with that name to be shown?
It's actually custom post type and I am using WP_Query to query posts ?
Thanks,
Peter
I don't believe there is such a function. But you could easily add this functionality to a vanilla WP_Query loop. Here's one solution that uses an array to "remember" post names during iteration:
<?php
// The Query
$the_query = new WP_Query( $args );
// an array to remember titles
$titles = array()
// The Loop
while ( $the_query->have_posts() ) : $the_query->the_post();
$the_title = get_the_title(); // (1) grab the current post title
if ($titles[$the_title]) continue; // (2) duplicate title: skip post!
$titles[$the_title] = TRUE; // (3) otherwise, remember the title
// ..do post stuff..
endwhile;
// Reset Post Data
wp_reset_postdata();
?>
The lookup for (2) is fast because Array is implemented as a map in PHP. See Arrays for more info.
Related
I'm using WordPress with a template that generates a pretty nice thumbnail for each post depending on Ids, and type of post. (ref:https://blinkdemo.wordpress.com/)
Since I've been asked to create a custom page that could show certain post from a category, I decided to create a query for a template page that checks the page slug and then list the posts containing a certain category + a tag ('comparativas').
The problem that I'm facing is that the list of post presented on the page doesn't show up the corresponding thumbnail on each post.
Thumbnails are generated dynamically basically with these lines:
$post_id = $post->ID;
$thumbnail_id = get_post_thumbnail_id( $post_id );
$thumbnail_image = wp_get_attachment_image_src( $thumbnail_id,$thumbnail_size );
The problem is that I couldn't find the way to send to the specific post ids to the function above, since the main $wp_query->posts; retrieves the page id instead of the post requested by the query_posts method.
The loops present the correct posts but when I echo the post->ID it shows the page id.
My query is:
global $wp_query;
// concatenate the query
$args = 'cat='.$idCategory.'&tag=comparativas';
query_posts( $args );
$posts = $wp_query->posts;
$current_id = get_the_ID(); //-> this returns the page id
If you could please tell me how to overwrite the global $wp_query; so the template can handle the corresponding ids for the list of post It would be great.
Any clue?
Best,
Juan
You could use, setup_postdata($post)
Then get_the_ID() works again :)
It doesn't work just because you aren't looping through them. You can do it many ways.
The 2 more common are the following:
overwrite the query with query_posts
$args = array('cat' => $idCategory,'tag' => 'comparativas');
query_posts($args);
if(have_posts()){
while(have_posts()){
the_post();
$current_id = get_the_ID(); // this return what you want now
the_title(); // this works as expected
}
}
wp_reset_query(); // get previous query back
get an array of WP_Post objects and setup_postdata or simply loop through them
$args = array('cat' => $idCategory,'tag' => 'comparativas');
$posts_i_want = get_posts($args);
foreach( $posts_i_want as $post ){
setup_postdata($post);
$current_id = get_the_ID(); // this return what you want now
the_title(); // this works as expected
}
wp_reset_postdata(); // get previous postdata back
I personally prefer the first in most cases
Cheers
I am trying to get custom posts with WP_Query but it's not returning only custom post type posts but also default posts too.
I am using
$args = array (
'post_type' => array ('survey')
);
$sPosts = new WP_Query($args);
as a result I am getting 'survey' posts as well as default posts, I only need it to return 'survey' posts.
P.S. when I use query_posts() it returns the required result, but just not getting it done with WP_Query and I prefer to use WP_Query not the query_posts()
Please try it like that....
<?php
$new = new WP_Query('post_type=discography');
while ($new->have_posts()) : $new->the_post();
the_content();
endwhile;
?>
I believe this custom query should actually be your main query, in which case you should not use a custom query
The problem you are facing is either due to
Wrong use somewhere of pre_get_posts. Remember, pre_get_posts alters all instances of WP_Query, backend and front end. Lack of correct use will break all queries
You have not changed the loop to be objects of your new query
To come back to the point, as said, this is suppose to be the main query, so lets target that problem.
The first thing to do would be to delete the custom query. Once you have done this, you would only see normal post.
We are now going to use pre_get_posts to alter the main query to only show custom posts. Paste the following inside your functions.php
add_action( 'pre_get_posts', function ( $q ) {
if( !is_admin() && $q->is_main_query() && $q->is_home() ) {
$q->set( 'post_type', 'YOUR CPT' );
}
});
You should now just see post from your cpt on the homepage
EDIT
Your index.php should look something like this
if( have_posts() ) {
while( have_posts() ) {
the_post();
// HTML mark up and template tags like the_title()
}
}else{
echo 'No posts found';
}
This code can get all the posts in a custom post type..,
wp_query is the function can get all the posts in the custom post type. wp_query requires array, so you can give the custom post type name in post id to array
$args = array(
'post_type' => 'address', //custom post type
'posts_per_page' => -1 // get all posts
);
$query = new WP_Query( $args );
// Check that we have query results.
if ( $query->have_posts() ) {
// Start looping over the query results.
while ( $query->have_posts() ) {
$query->the_post();
echo( get_the_title() );
}
}
The docs discussing WP_Query() clearly state that this should work:
$query = new WP_Query( 'category_name=tools,wordpress' );
However, if I use WP_Query's class method ->get_posts():
$query->get_posts();
I only get the posts from tools (8 posts in total).
However, if I do:
while($query->have->posts()) { ... }
I can loop through all the posts (12 posts in total) as expected.
Is this by design, a design flaw, or a bug?
[EDIT] Here's the actual code I'm using:
// query
$query = 'category_name=tools,wordpress&orderby=date&order=asc&posts_per_page=-1';
$wpq = new WP_Query($query);
// loop-style version - shows all 12 posts
while($wpq->have_posts())
{
$post = $wpq->next_post();
echo "<p>{$post->post_title}</p>";
}
// get_posts()-style version, only shows 8 posts from tools
$posts = $wpq->get_posts();
foreach($posts as $post)
{
echo "<p>{$post->post_title}</p>";
}
Thanks,
Dave
OK, I looked at the code inside the standalone function get_posts() and it provided the answer.
As with most things WordPress it's completely inconsistent!
You have to use WP_Query->query(); and not WP_Query->get_posts();
// query
$query = 'category_name=tools,wordpress&orderby=date&order=desc&posts_per_page=-1';
$wpq = new WP_Query();
// new query() syntax has functionality of loop-style version but behaves like get_posts()
$posts = $wpq->query($query);
foreach($posts as $post)
{
echo "<p>{$post->post_title}</p>";
}
// debug
printr($wpq);
Such a shame the WordPress API blows so badly.
[EDIT] Have just looked inside ->query() and it uses ->get_posts() internally. These simple calls should not all be having different behaviour.
Well you are mixing things a little:
get_posts() - Retrieve list of latest posts or posts matching criteria.
You can use get_posts() by passing the argumets to it and it will alter the main query for you (which is not recommended)
WP_Query - The WordPress Query class.
This allows you to create new queries in the wp database.
get_posts() it's a method of WP_Query class
Check the links above they have examples on how to get posts by multiple categories. Also check Sandeep Kumar answer.
Your example can also be used:
// The Query
$query = new WP_Query( 'category_name=staff,news' );
// The Loop ! there is no get_posts()!
if ( $query->have_posts() ) {
while ( $query->have_posts() ) { ... }
}
An example using get_posts() is:
$args = array('category' => '1,2' ); //where 1 and 2 are the posts categories id's
$myposts = get_posts( $args );
foreach ( $myposts as $post ) {
setup_postdata( $post );
...
}
wp_reset_postdata();
Also have a look at pre_get_posts() documentation see if you can't use this one as it changes the query before it gets to the database, if you can use it, it will save you a trip to the database per page load.
Show Posts From Several Categories
Display posts that have these categories, using category id:
$query = new WP_Query( 'cat=2,6,17,38' );
I think that would help you if not then can you provide me complete code so that i can check and provide you complete solution.
What's the trick to working with WordPress posts as pure data structures?
Traditionally, you use "The Loop" and output data via functions like this:
<?php the_title(); ?>
<?php the_content(); ?>
These functions dump text directly into the response.
Using $wpdb, I can get back an array of posts like this:
$posts = $wpdb->get_results("SOME SQL HERE", OBJECT);
I then get a array of stdClass objects which are...Post-ish, I guess. They have properties for "post_title" and such, but there's no Permalink, which makes me think this isn't the "correct" Post object to use. Also, the "post_content" isn't complete HTML -- it still has line-breaks, etc.
When iterating this array, I've found I have to do this:
foreach ($events as $post)
{
setup_postdata($post);
...
This puts that post in the global scope. Then I can use the aforementioned functions to write content out, and use functions like this to get metadata:
$display_date = get_custom_field('display_date');
Is there a better way? This just seems...odd. Is there a way to get a complete representation of a post as an object, with all metadata, and everything else I need to manipulate it from the data level, rather than just assuming I want to dump output to the response?
You can use WP_Query instead, just like
$the_query = new WP_Query( $args );
while ( $the_query->have_posts() ) : $the_query->the_post();
echo '<li>' . get_the_title() . '</li>';
endwhile;
All you have to prepare the $args arguments array to make a customized query, for example, you can use
// Display posts that have "books" tag
$the_query = new WP_Query( 'tag=books' );
or
// Display posts that have these categories
$the_query = new WP_Query( 'category_name=event,news' );
or more complex one like
// Display posts tagged with bob, under people custom taxonomy
$args = array(
'post_type' => 'post',
'people' => 'bob'
);
$the_query = new WP_Query( $args );
You can also use query_posts but it's a bit different than WP_Query and you can also use get_post and use a custom select query only when there is no way to get the desired result using WordPress' way. There is a nice answer about WP_Query vs query_posts() vs get_posts(), read this for better understanding.
I have made a shortcode inside my plugin, which is working great .
The shortcode needs to take some parameters and create a custom loop with output.
One of the parameters is how many posts to output the loop for ($markers)
$args=array(
'meta_key'=>'_mykey',
'post_status'=>'publish',
'post_type'=>'post',
'orderby'=>'date',
'order'=>'DESC',
'posts_per_page'=>$markers,
);
$wp_query = new WP_Query();
$wp_query->query($args);
if ($wp_query->have_posts()) : while (($wp_query->have_posts()) ) : $wp_query->the_post();
// do the loop using get_the_id() and $post->id
endwhile;endif;
wp_reset_query();//END query
On occations I will need to have data from ALL posts ($markers = '-1' ) and sometimes only one ($markers = '1' ) or muliple ($markers = 'x').
All of those work great on single pages / posts - but My problem is that when this function is in a place where I have more than one post (!is_single) and ($ markers = '1' )it will always return the data for the LATEST post , and not for the correct one ..
(for example in the default wordpress theme, where it would display10 posts - they will all be the same data )
It is obviously a problem of the $post->ID - but how can I have the correct post ID when doing a custom loop OUTSIDE the wp loop ?
I tried to ovverride the problem by
global $post;
$thePostIDtmp = $post->ID; //get the ID before starting new query as temp id
$wp_query = new WP_Query();
$wp_query->query($args);
// Start Custom Loop
if (!is_single()){
$post_id_t = $thePostIDtmp;}
else {
$post_id_t = $post->ID;}
and then use $post_id_t - but it did not seems to work ,
Should I not use get_the_id() ? or should I not use query (and use get_posts) ??
Any ideas / solutions / thoughts ??
I would use query_posts(http://codex.wordpress.org/Function_Reference/query_posts)rather than override the $wp object. You should be able to include as many loops on the page as you want with this. If you have problems with this you can use: http://codex.wordpress.org/Function_Reference/wp_reset_query just before you call it.
I find this: http://blog.cloudfour.com/wordpress-taking-the-hack-out-of-multiple-custom-loops/
takes a bit of the pain away too.
There are basically two sorts of querying posts in WordPress: Those that alter the main loop and those that do not. If you want to change the main loop like the one used to display category archive pages then use query_posts. It let's you do exactly that. Delete, change and append parameters of the default query to change the outcome of a typical page.
query_posts has some drawbacks though.
Then there are queries that are just used to get stuff out of the database to play around with e.g. displaying the latest post titles in the sidebar or the attachments of the current post.
To do that create a new WP_Query object that will build your custom loop independently of the main loop like so:
// The Query
$the_query = new WP_Query( $args );
// The Loop
while ( $the_query->have_posts() ) : $the_query->the_post();
echo '<li>';
the_title();
echo '</li>';
endwhile;
// Reset Post Data
wp_reset_postdata();
Then there is get_posts() which is like the little brother of WP_Query. It has an easier interface in my opinion and returns an array with the results that is easier to work with.
It looks like this:
$myposts = get_posts( $args );
foreach($myposts as $post) : setup_postdata($post);
echo "<li>";
the_title();
echo "</li>";
endforeach;
Inside the foreach template tags like get_the_id() will work.