WordPress use wildcard in get_posts - php

Is it possible to use a wildcard in the get_posts() function?
I have made the query I wanted in SQL already:
select * from wp_posts p
left join wp_postmeta pm on p.id = pm.post_id
where pm.meta_key like 'additional_downloads%' and pm.meta_value = 81 and p.post_status = "publish"
Which gives me the results I want.
Then I tried using to do that with the built-in get_posts() function in WordPress:
get_posts(array('meta_key' => 'additional_downloads%', 'meta_value' => 81))
But that gives me 0 results. The reason I need this wildcard is because a post can have more than 1 additional download, and those are stored in the wp_postmeta table with the meta_keys 'additional_downloads_0', 'additional_downloads_1' etc etc
Any idea how to do this using the wordpress functions?

We can filter the WHERE clause of the query.
THE FILTER
add_filter( 'posts_where', function ( $where, \WP_Query $q )
{
// Check for our custom query var
if ( true !== $q->get( 'wildcard_on_key' ) )
return $where;
// Lets filter the clause
$where = str_replace( 'meta_key =', 'meta_key LIKE', $where );
return $where;
}, 10, 2 );
THE QUERY
$args = [
'suppress_filters' => false,
'wildcard_on_key' => true,
'meta_query' = [
[
'key' => 'additional_downloads_%',
'value' => 81
]
]
];
$q = get_posts( $args );

Related

How do I retrieve data as a Wp_query object with this custom mysql query?

SELECT
IF (POSITION('Villa' IN p.post_title )>=1,
SUBSTRING(p.post_title, 7), post_title) AS 'Title',
p.post_title,
p.ID,
p.post_content
FROM wp_posts p INNER JOIN wp_term_relationships tr
ON p.ID=tr.object_id where tr.term_taxonomy_id=4
and p.post_status='publish'
ORDER BY Title ASC;
I can run above query to get data with "wpdb" function like
$wpdb->get_results($query);
But I need the above results to be returned as a Wp_query object as I want to use functions like get_the_excerpt()
The orderby parameter accepts the post__in sorting value as a possible way to sort posts returned. With orderby set to post__in, the posts will be returned in the order they are entered into the post__in parameter.
The following code
args = [
'post__in' =>[3, 1, 2],
'orderby' => 'post__in'
];
$q = new WP_Query( $args );
will return posts 1,2, and 3 in the following order
3,1,2
Try this code,
$args = array(
'post_type' => $post_type,
'posts_per_page' => -1,
'post_status'=>'publish',
'orderby'=>'title',
'order' => 'ASC',
'tax_query' => array(
array(
'taxonomy' => $taxonomy,
'field' => 'id',
'terms' => 4
)
)
);
$query = new WP_Query($args);
$query_posts = $query->posts;
var_dump($query_posts);
You can take your WPDB results and use the post functions like this...
global $wpdb;
global $post;
$query = "SELECT
IF (POSITION('Villa' IN p.post_title )>=1,
SUBSTRING(p.post_title, 7), post_title) AS 'Title',
p.post_title,
p.ID,
p.post_content
FROM wp_posts p INNER JOIN wp_term_relationships tr
ON p.ID=tr.object_id where tr.term_taxonomy_id=4
and p.post_status='publish'
ORDER BY Title ASC;"
$result = $wpdb->get_results( $query );
foreach( $result as $post )
{
setup_postdata( $post );
echo "<div>" . get_the_excerpt() . "</div>";
}
Make sure you set the $post global.

WordPress - Search posts by Taxonomy

My custom wp search query in
$args = array(
'post_type' => 'post',
'taxonomy' => 'location',
'field' => 'name',
'posts_per_page' => 10,
'term' => $keyword,
);
$wp_query = new WP_Query($args);
I have 2 post which location is London and oxford,london .Now when i search london then it show only 1 post**(1st one)** .Also when i search oxford then it show no result found.
When i search oxford london then its working fine.
Befor WP_Query Run write this code
function advance_search_where($where){
global $wpdb;
if (is_search())
$where .= "OR (t.name LIKE '%".get_search_query()."%' AND {$wpdb->posts}.post_status = 'publish')";
return $where;
}
function advance_search_join($join){
global $wpdb;
if (is_search())
$join .= "LEFT JOIN {$wpdb->term_relationships} tr ON {$wpdb->posts}.ID = tr.object_id INNER JOIN {$wpdb->term_taxonomy} tt ON tt.term_taxonomy_id=tr.term_taxonomy_id INNER JOIN {$wpdb->terms} t ON t.term_id = tt.term_id";
return $join;
}
function advance_search_groupby($groupby){
global $wpdb;
// we need to group on post ID
$groupby_id = "{$wpdb->posts}.ID";
if(!is_search() || strpos($groupby, $groupby_id) !== false) return $groupby;
// groupby was empty, use ours
if(!strlen(trim($groupby))) return $groupby_id;
// wasn't empty, append ours
return $groupby.", ".$groupby_id;
}
add_filter('posts_where','advance_search_where');
add_filter('posts_join', 'advance_search_join');
add_filter('posts_groupby', 'advance_search_groupby');
Now Run Your WP_Query Like this
$args = array(
'post_type' => 'post',
'posts_per_page' => 10,
's' => $keyword,
);
$wp_query = new WP_Query($args);
After all your result and that you want you have to just remove the above filter coz if you not remove that then it will apply in other wp_query of that page.
remove_filter('posts_where','advance_search_where');
remove_filter('posts_join', 'advance_search_join');
remove_filter('posts_groupby', 'advance_search_groupby');

How To Exclude Results From Custom WordPress MySQL Query By Taxonomy Term

I only want to show posts which do not have the term 'brand-slug' for the taxonomy 'product-brand'.
My current query doesn't apply the filter:
SELECT DISTINCT * FROM $wpdb->posts AS p
LEFT JOIN $wpdb->postmeta AS meta ON p.ID = meta.post_id
LEFT JOIN $wpdb->term_relationships AS rel ON rel.object_id = p.ID
LEFT JOIN $wpdb->term_taxonomy AS tax ON tax.term_taxonomy_id = rel.term_taxonomy_id
LEFT JOIN $wpdb->terms AS term ON tax.term_id = term.term_id
WHERE 1=1
AND p.post_type = 'product'
AND p.post_status = 'publish'
AND p.post_title LIKE '%$trimmed%' OR (meta.meta_key = 'product_model' AND meta.meta_value LIKE '%$trimmed%')
AND (tax.taxonomy = 'product-brand' AND term.slug NOT IN ('$protected'))
Neither taxonomy or slug conditionals seem to be working in the above query.
Any help is appreciated!
Notes:
It looks like you're not using $wpdb->prepare(), so you risk SQL injections.
I also think you're missing parentheses around the relevant OR parts, so you don't end up displaying drafts, for example.
Alternative:
Instead of writing an hardcoded SQL query, we should be able to use the WP_Query class, with some modifications through hooks/filters.
Here's an example (PHP 5.4+):
$args = [
'_meta_or_like_title' => $trimmed, // Our new custom argument!
'post_type' => 'product',
'post_status' => 'publish',
'meta_query' => [
[
'key' => 'product_model',
'value' => $trimmed, // Your meta value
'compare' => 'LIKE'
]
],
'tax_query' => [
[
'taxonomy' => 'product-brand',
'field' => 'slug',
'terms' => $protected, // Your terms array
'operator' => 'NOT IN'
]
]
];
where the custom _meta_or_like_title argument is supported by a slightly modified plugin I wrote for another question here.
Plugin:
<?php
/**
* Plugin Name: Meta OR LIKE Title query in WP_Query
* Description: Activated through the '_meta_or_like_title' argument of WP_Query
* Plugin URI: http://stackoverflow.com/a/31241416/2078474
* Plugin Author: Birgir Erlendsson (birgire)
* Version: 0.0.1
*/
add_action( 'pre_get_posts', function( $q )
{
if( $title = $q->get( '_meta_or_like_title' ) )
{
add_filter( 'get_meta_sql', function( $sql ) use ( $title )
{
global $wpdb;
// Only run once:
static $nr = 0;
if( 0 != $nr++ ) return $sql;
// Modify WHERE part:
$sql['where'] = sprintf(
" AND ( %s OR %s ) ",
$wpdb->prepare(
"{$wpdb->posts}.post_title LIKE '%%%s%%'",
$wpdb->esc_like( $title )
),
mb_substr( $sql['where'], 5, mb_strlen( $sql['where'] ) )
);
return $sql;
});
}
}, PHP_INT_MAX );

SQL Query for multiple values and multiple keys in the same table

Every post has two post meta: year and month (custom)
I need SQL query to pull all posts that have
wp_postmeta.meta_key = year AND wp_postmeta.meta_value = 2013
AND AT THE SAME TIME another meta_key / meta_value pair
wp_postmeta.meta_key = month AND wp_postmeta.meta_value BETWEEN 1 AND 12 ;
SELECT * FROM wp_postmeta
WHERE (meta_key = 'agam_post_options_year' AND meta_value = 2013)
OR (meta_key = 'agam_post_options_month' AND meta_value BETWEEN 0 AND 12 )
GROUP BY meta_value;
This is something I tried and a couple of more variations but it doesn't do much... this specifically gives me one post that has year 2013 and 12 posts that have either 1 or ... to 12 for month field}
Please replace _PUT_YOUR_POST_ID_FIELD_HERE_ by something appropriate field from that table and try to run...
SELECT Y.meta_value, M.meta_value FROM wp_postmeta as Y
JOIN wp_postmeta AS M USING (_PUT_YOUR_POST_ID_FIELD_HERE_)
WHERE (Y.meta_key = 'agam_post_options_year' AND Y.meta_value = 2013)
AND (M.meta_key = 'agam_post_options_month' AND M.meta_value BETWEEN 0 AND 12 )
GROUP BY Y.meta_value, M.meta_value;
OK It was all good. The reason it took out the "duplicates" was because we didn't group by Y.meta_id and instead we used meta_value
If you don't really need a pure SQL query and you're getting these posts for using them in WordPress, you could use meta_query array passed as a part of args to WP_Query class or get_posts() function.
$args = array(
'posts_per_page' => -1,
'post_type' => 'your-post-type', // default 'post'
'meta_query' => array(
relation => 'AND', // default 'AND' it might be 'OR'
array(
'key' => 'agam_post_options_year',
'value' => '2013',
'compare'=> '=',
'type' => 'NUMERIC' // see docs for more types
),
array(
'key' => 'agam_post_options_month',
'value' => array( 0, 12 ),
'compare' => 'BETWEEN',
'type' => 'NUMERIC' // see docs for more types
)
)
);
$posts = get_posts( $args ); // returns an array of posts objects
//OR
$query = new WP_Query( $args ); // returns a new WP_Query object
Hope it helps! : )

I have query to retrieve all posts in wordpress but how can i check the condition for post meta_key =“develop” and meta_value='anything'

SELECT DISTINCT date(p.post_date) as post_date
FROM $wpdb->posts p
LEFT JOIN $wpdb->postmeta pm ON p.ID = pm.post_id
WHERE p.post_status='publish'
AND p.post_type IN ('%s')
ORDER BY p.post_date DESC
Here it reads all dates of the posts. My problem is that query should exclude the posts which has meta_value(it can be anything) of which meta_key="develop" . How can i write the query for that ?
I feel it will be in this form for wp_query
$args[ 'meta_query' ]= array (
'relation'= >' AND ',
array (
'key' = > 'respect'
),
array (
'key' => 'develop',
'compare' => 'NOT EXISTS'
)
);
$query = new Wp_query($args);
So you're trying to get all posts that don't have a meta key equal to "develop"?
You could do this:
$query = new WP_Query( array(
'meta_key' => 'develop',
'meta_compare' => 'NOT EXISTS'
) );
Also, see this note from the Codex if you're using a version of Wordpress less than 3.9:
"(Note: Due to bug #23268, value is required for NOT EXISTS comparisons to work correctly prior to 3.9. You must supply some string for the value parameter. An empty string or NULL will NOT work. However, any other string will do the trick and will NOT show up in your SQL when using NOT EXISTS. Need inspiration? How about 'bug #23268'.)"

Categories