i am working with wordpress,And i want to pass one parameter name "post_title" in wp_query,So i can change query and can get correct data,But my query is not changed(not displaying as i expected),I tried with following code
$args = array(
'post_type' => 'user',
'posts_per_page' => -1,
'post_title' => $_GET['post_title'],
'post_status' => [ 'publish']
);
$query = new WP_Query($args);
when i print my $query->request then i getting following query
[request] = "SELECT MZAGsQVeposts.* FROM MZAGsQVeposts WHERE 1=1 AND MZAGsQVeposts.post_type = 'user' AND ((MZAGsQVeposts.post_status = 'publish')) ORDER BY MZAGsQVeposts.post_date DESC";
But expected query is
"SELECT MZAGsQVeposts.* FROM MZAGsQVeposts WHERE 1=1 AND MZAGsQVeposts.post_type = 'user' AND ((MZAGsQVeposts.post_status = 'publish')) AND MZAGsQVeposts.post_title='Lisa I' ORDER BY MZAGsQVeposts.post_date DESC";
Where i am wrong ? Thanks in advance.
Unfortunately you can't query posts by title in wp_query, it's not a recognised argument. (See WP_Query for more info) however you can use get_page_by_title and pass the title that way and it'll return the post object with that title.
Related
I have this query that works fine:
$query = new WP_Query(array( 's' => $keyword ,'post_status' => array('publish', 'pending', 'draft')) );
Its searches and finds the post with the keyword in title.
I want to query posts with a few keywords at once, (Now i'm doing a loop over all keywords and query each keyword by itself.
If it was mysql it would have be something like:
Select * from ..... where title='keyword1' or title='keyword2' or title='keyword3' ;
How could achieve that with WP_Query?
You can't do it using the WP_Query directly.
An alternative for looping the WP_Query is use the $wpdb.
$wpdb->get_row( "SELECT * FROM $wpdb->posts WHERE where title='keyword1' or title='keyword2' or title='keyword3'" );
U have to use $wpdb (#codex)
$query= $wpdb->get_results( $wpdb->prepare(
"SELECT * FROM ....
WHERE title= %s OR
title=%s OR
title = %s
",
$keyword1,
$keyword2,
$keyword3
) );
I hope that help u:)
So I have the following
SELECT wp_posts.ID, wp_posts.post_author,wp_posts.post_date,wp_posts.post_content,wp_posts.post_title,wp_posts.post_excerpt,wp_postmeta.meta_value
FROM wp_posts
INNER JOIN wp_postmeta
ON wp_posts.id=wp_postmeta.post_id
WHERE wp_postmeta.meta_key='cm_video' and post_status='publish'
ORDER BY wp_posts.id DESC;
Which brings back what I need (almost). The meta_value is in the form
a:2:{s:4:"code";s:27:"http://youtu.be/xpiL05fCE1E";s:4:"type";s:7:"youtube";}
What's the easiest way to bring back just http://youtu.be/xpiL05fCE1E? There are various other values that can be present in here such as embed and iframe code.
Is there something internal to WordPress I should use?
I've come up with this which seems to do the trick. Thoughts?
SELECT
wp_posts.ID, wp_posts.post_author,wp_posts.post_date,wp_posts.post_content,wp_posts.post_title,wp_posts.post_excerpt,SUBSTRING_INDEX(SUBSTRING_INDEX(wp_postmeta.meta_value, '";', 2), ':"', -1)
FROM wp_posts
INNER JOIN wp_postmeta
ON wp_posts.id=wp_postmeta.post_id
WHERE wp_postmeta.meta_key='cm_video' and post_status='publish'
Thanks
use unserialize() method
$a='a:2:{s:4:"code";s:27:"http://youtu.be/xpiL05fCE1E";s:4:"type";s:7:"youtube";}';
$a = unserialize($a);
print_r($a);
//output
Array ( [code] => http://youtu.be/xpiL05fCE1E [type] => youtube )
echo $a['code'];
Here are two types of variable
a = array and 2 is the dimension of the array
s = string and 4 is the length of the string
We will get the same with a proper format with wp_query :
$query = new WP_Query( array (
'post_type' => 'product',
'orderby' => 'meta_value_num',
'meta_key' => 'cm_video' ) );
print_r($query);
Now if $query object have the code elements in it with your value. Print it :
echo $query->code;
Hope it will work for you please let me know if you need any further help.
Is there any way to see if a post exists by a meta value?
For instance, lets say I want to see if another post has a unique meta value of "pictureID", and if so do something else.
Is there a way I could write that clause in php?
Thank you
if you dont know the post id then
you can use custom wordpress query to check post meta according to key like
global $wpdb;
$wpdb->get_results( "select * from $wpdb->postmeta where meta_key = 'pictureID' " );
And then you can get all results with post id and then get that post data.
Hope this helps ;)
You can use a standard WP_Query to return posts by meta_key using the meta_query argument and EXISTS compare type.
// query for all posts with the pictureID meta key set
$args = array(
'post_type' => 'post', // or your_custom_post_type
'meta_query' => array(
array(
'key' => 'pictureID',
'compare' => 'EXISTS',
),
),
}
// create a custom query
$my_query = new WP_Query( $args );
// loop over your query, creating a custom The Loop
if ( $my_query->have_posts() ): while ( $my_query->have_posts() ): $my_query->the_post();
// $post is now posts that have a pictureId meta value
endwhile; endif;
// reset $post
wp_reset_postdata();
If you want to quickly grab a random post_id that has this meta_key set you can go to the database directly (bypassing caching, etc).
global $wpdb;
// SQL statement to fetch the post_id using a meta_key and a published post
$sql = <<<SQL
SELECT post_id
FROM {$wpdb->postmeta} pm
JOIN {$wpdb->posts} p
ON p.ID = pm.post_id
AND post_status = 'publish'
AND post_type = 'post'
WHERE meta_key = 'pictureID'
AND meta_value != ''
AND post_id != %d
ORDER BY RAND()
LIMIT 1
SQL;
// exclude the current post by replacing %d with the current ID
$sql = $wpdb->prepare( $sql, $post->ID );
// use get_var() to return the post_id
$post_id = $wpdb->get_var( $sql );
first try to get meta value for post get_post_meta()
$postMetaValue=get_post_meta($postId,"meta_key",true);
if($postMetaValue=='pictureID')
{
//do as you want
}
i would like to get date gmt of latest comment for post ID. Result i would like to get as a string.
Can somebody help me how to set result into string:
function GetLastCommentDate( $postId ) {
global $wpdb;
$dateOutput = '0000-00-00 00:00:00';
$commentRes= $wpdb->get_results("SELECT DISTINCT `comment_date_gmt` FROM `wp_comments` WHERE `comment_approved` ='1' AND `comment_post_ID` = '". $postId. "' ORDER BY `comment_date_gmt` DESC LIMIT 1");
if(!empty($commentRes)) {
$dateOutput = ...........
}
return $dateOutput;
}
One answer is like this:
$commentRes= $wpdb->get_results("SELECT DISTINCT `comment_date_gmt` as `comment_date_gmt` FROM `wp_comments` WHERE `comment_approved` ='1' AND `comment_post_ID` = '". $postId. "' ORDER BY `comment_date_gmt` DESC LIMIT 1");
if(!empty($commentRes)) {
foreach($commentRes as $comment) {
$dateOutput=$comment->comment_date_gmt;
}
}
return $dateOutput;
But how to avoid foreach loop? There is only one row (sql limit set to 1).
You need not query wordpress database directly. WP provides an API to retrieve this.
$comments = get_comments( array(
'post_id' => $post->ID,
'orderby' => 'comment_date_gmt',
'status' => 'approve',
'number' => 1
) );
Check out this API reference. Specifying number as 1 returns only the last comment.
The date value for last comment can be retrieved as $comments[0]['date']
Now that you want to use this from outside, include the following at top of your php code
require('/the/path/to/your/wp-blog-header.php');
Check out this wordpress doumentation
If you get an out of loop error try adding this code.
The loop starts here:
<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
and ends here:
<?php endwhile; else: ?>
<p><?php _e('Sorry, no posts matched your criteria.'); ?></p>
<?php endif; ?>
I think you want something like this;
$commentRes= $wpdb->get_row(
"SELECT `comment_date_gmt` FROM `wp_comments` ".
"WHERE `comment_approved` ='1' AND `comment_post_ID` = '$postId' ".
"ORDER BY `comment_date_gmt` DESC LIMIT 1");
if(!empty($commentRes))
$dateOutput = date("Y-m-d H:i:s", $commentRes->comment_date_gmt);
I've stumbled upon this while searching for something else. I know that the question is old, and the aswers too, but somebody can find it like I did, and I'd like to add another updated solution.
function GetLastCommentDate( $postId ) {
$dateOutput = false; //this will make easier to check if there are no comments
//get_comments() args https://codex.wordpress.org/Function_Reference/get_comments
$args = array(
'post_id' => $postId, //just comments of this post
'number' => 1, //just one comment
'order_by' => 'comment_date_gmt', //order by comment date gmt
'order' => 'DESC', //latest first
);
//retrieve comments
$comments = get_comments($args);
if ($comments){
$dateOutput = $comments[0]->comment_date;
}
return $dateOutput;
}
And you can use it wherever you want like this:
$postId = '12345';
$lastCommentDate = GetLastCommentDate($postId) ?: 'Never';
echo $lastCommentDate;
I'm wanting to order Wordpress posts by the most recent comment. To the best of my knowledge this isn't possible using the WP_Query object, and would require a custom $wpdb query, which I can easily write. However, I then don't know how to setup the loop to run off this object.
Can anyone help?
Assign
select wp_posts.*, max(comment_date) as max_comment_date
from $wpdb->posts wp_posts
right join $wpdb->comments
on id = comment_post_id
group by ID
order by max_comment_date desc
limit 10
to some variable $query. You can fiddle around with the 10 or the query itself. (I'm no SQL optimization ninja.) Then your code will look something like
<?php
$results = $wpdb->get_results($query) or die('!');
foreach ($results as $result):
?>
[insert template here]
<?php endforeach ?>
This pattern is covered in more depth by the Codex.
I used a simpler, portion of a native WP in function. hope it helps and some one can continue to develop. Here is a simplified version that shows the title & excerpt of the post along with the comment content & author from the latest commented posts using get_comments.
$args = array(
'status' => 'approve',
'number' => 6,
'order' => 'DESC'
);
$comments = get_comments($args);
foreach($comments as $comment) : $count++;
$post_args = array(
'post_type' => 'post',
'p' => $comment->comment_post_ID,
'posts_per_page' => 1
);
$posts = get_posts($post_args);
foreach($posts as $post) : setup_postdata($post);
the_title();
the_excerpt();
endforeach;
echo $comment->comment_content;
echo $comment->comment_author;
endforeach;
OK guys,
A lot of great answers here, but obviously nobody's taken the time to test them.
Hao Lian gets the credit for the first best original answer, but unfortunately his code doesn't show posts without comments.
Captain Keytar is on the right track, but his code will display every single post and attachment as a separate result.
Here is a modified version of Captain Keytar but it limits the results to the type 'post'.. that has been published (to avoid getting drafts!!)
select wp_posts.*,
coalesce(
(
select max(comment_date)
from $wpdb->comments wpc
where wpc.comment_post_id = wp_posts.id
),
wp_posts.post_date
) as mcomment_date
from $wpdb->posts wp_posts
where post_type = 'post'
and post_status = 'publish'
order by mcomment_date desc
limit 10
This is an old question, but I had the same issue and found a much cleaner way to do this, so I'm posting it here in case it helps anyone.
If you use the posts_clauses filter you can then just modify the main query and still use The Loop and all the regular loop functions.
function intercept_query_clauses( $pieces ) {
global $wpdb;
$pieces['fields'] = "wp_posts.*,
(
select max(comment_date)
from " . $wpdb->comments ." wpc
where wpc.comment_post_id = wp_posts.id AND wpc.comment_approved = 1
) as mcomment_date";
$pieces['orderby'] = "mcomment_date desc";
return $pieces;
}
add_filter( 'posts_clauses', 'intercept_query_clauses', 20, 1 );
Note that I changed the sql slightly for my own purposes, but the general concept is the same.
As an addendum to Hao Lian's answer, if you use the following query:
select wp_posts.*,
coalesce(
(
select max(comment_date)
from $wpdb->comments wpc
where wpc.comment_post_id = wp_posts.id
),
wp_posts.post_date
) as mcomment_date
from $wpdb->posts wp_posts
order by mcomment_date desc
limit 10
This mixes in posts that don't have comments yet, and sorts them by post_date and max(comment_date).
Code suggested by Hao Lian works perfect except for the fact that we should add the following WHERE clause to avoid pulling POST with comment_count = 0, this situation is caused by spam comments.
The WHERE clause to add is as follows:
WHERE comment_approved = '1' AND comment_type = '' AND post_password = ''
Complete code after adding the where clause shoud look like following:
select wp_posts.*, max(comment_date) as comment_date
from wp_posts
right join wp_comments on id = comment_post_id
WHERE comment_approved = '1' AND comment_type = '' AND post_password = ''
group by ID
order by comment_date desc
limit 6
This can be done by combining WP_Comment_Query with WP_Query, like this:
// For performance, limit the number of queried comments,
// but make it be something big enough to account for "duplicate" posts.
$comments_query = new WP_Comment_Query;
$comments = $comments_query->query( array( 'number' => '100' ) );
if ( $comments ) {
foreach ( $comments as $comment ) {
// You'll want to convert the dates from string to integer so you can sort them out later
$comment_utf = strtotime($comment->comment_date);
// Build an array of post IDs with the date of the last published comment
$latest_comments[$comment->comment_post_ID] = $comment_utf;
}}
// Sort the array by date
arsort($latest_comments); foreach ($latest_comments as $key => $value) { $posts_ordered[] = $key; }
// The nice thing is that WP_Query will remove duplicates by default
$args = array ( 'posts_per_page' => '10', 'post__in' => $posts_ordered, 'orderby' => 'post__in');
$query = new WP_Query( $args );
if ( $query->have_posts() ) {
while ( $query->have_posts() ) {
$query->the_post();
// Do your stuff (add the template or whatever)
// If you want to add the comment itself, use this:
$comments = get_comments(array('number' => '1', 'post_id' => $post->ID));
foreach($comments as $comment) :
echo $comment->comment_content;
endforeach;
// That's about it
}}
wp_reset_postdata();
I'm thinking that adding in the max function will screw up your results. MySQL isn't going to pull the max from each one. It's going to pull the max from the full set. This is the query that'll get you your results:
select wp_posts.*, comment_date
from $wpdb->posts wp_posts
right join $wpdb->comments
on id = comment_post_id
group by ID
order by comment_date desc
limit 10
After that, if you want to follow WP convention, use this, and then you can use the functions that most of your templates are using (based on the loop):
$results = $wpdb->get_results($query) or die('!');
foreach ($results as $post):
setup_postdata($post);
Get 3 newest comments for custom post type 'question' regardless of approvement:
global $wpdb;
$results = $wpdb->get_results(
"
SELECT wp_posts.ID, MAX(comment_date) AS max_comment_date
FROM wp_posts
RIGHT JOIN wp_comments
ON id = comment_post_id
WHERE wp_posts.post_type = 'question'
AND wp_posts.post_status = 'publish'
GROUP BY ID
ORDER BY max_comment_date DESC
LIMIT 3
"
);
foreach ($results as $result) {
$posts_arr[] = $result->ID;
}
$args = array(
'post_type' => 'question',
'post__in' => $posts_arr,
'orderby' => 'post__in',
);
$the_query = new WP_Query( $args );
Using Lucian's BEAUTIFUL solution, I needed to alter/filter the existing WP_Query to sort posts by the latest comment. Here's the code, tested & works perfectly:
$comments_query = new WP_Comment_Query;
$comments = $comments_query->query( array( 'number' => '100' ) );
if ( $comments ) {
foreach ( $comments as $comment ) {
$comment_utf = strtotime($comment->comment_date);
$latest_comments[$comment->comment_post_ID] = $comment_utf;
}
// Sort the array by date
arsort( $latest_comments );
foreach( $latest_comments as $key => $value ) {
$posts_ordered[] = $key;
}
$query->set( 'post__in', $posts_ordered );
$query->set( 'orderby', 'post__in' );
}