I am trying to exclude some posts with a custom meta_key within the hook pre_get_posts but for some reason is not working, the posts are not getting excluded. Taxonomies to be excluded work, but posts no.
add_action('pre_get_posts' , 'changeCourseCountry');
function changeCourseCountry($query){
global $wpdb;
$tax_query_merge = array(
'relation' => 'AND',
array(
'taxonomy' => 'course_category',
'field' => 'slug',
'terms' => array('short-courses', 'mega-course'),
'operator' => 'NOT IN'
),
);
$tax_query = array_merge($tax_query, $tax_query_merge);
$exclude = $wpdb->get_col("SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_video_course'"); // here I get an array of posts
$query->set('tax_query' ,$tax_query);
$query->set('post__not_in', $exlcude);
return $query
}
Please use the following instead of getting the column data,
$exclude = $wpdb->get_row("SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_video_course'"); // here I get an array of posts
So it will be ,
add_action('pre_get_posts' , 'changeCourseCountry');
function changeCourseCountry($query){
global $wpdb;
$tax_query_merge = array(
'relation' => 'AND',
array(
'taxonomy' => 'course_category',
'field' => 'slug',
'terms' => array('short-courses', 'mega-course'),
'operator' => 'NOT IN'
),
);
$tax_query = array_merge($tax_query, $tax_query_merge);
$exclude = $wpdb->get_row("SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_video_course'",ARRAY_A); // here I get an array of posts
$query->set('tax_query' ,$tax_query);
$query->set('post__not_in', $exlcude);
return $query;
}
Also if you need multiple IDs then you need to use get_results and loop the array in foreach.
I also added ARRAY_A to $wpdb query to retrive the array.
Related
some of my products missing their images, what I'm trying to do is to make a query that will give me only products with the default image (woocommerce place holder image).
this is what i have tried :
$args = array(
'post_type' => 'product',
'posts_per_page' => -1,
'meta_query', array(
array(
'key' => '_thumbnail_id',
'value' => '5',
'compare' => '=='
)
)
);
i found place holder image id using this function :
attachment_url_to_postid("/wp-content/uploads/woocommerce-placeholder.png");
the query returns every single product I have, and not only those with the placeholder image, what causes it, and is there a better way?
You can check using meta_key _thumbnail_id. Try the below query.
global $wpdb;
$post_ids = $wpdb->get_results( "
SELECT ID FROM $wpdb->posts
WHERE ID NOT IN (
SELECT post_id from $wpdb->postmeta
WHERE meta_key = '_thumbnail_id'
)
AND post_type = 'product'
AND post_status = 'publish'
" );
echo "<pre>"; print_r( $post_ids ); echo "</pre>";
I have multiple products, whose sku names are like AL-888, A-2323, AL-etrere.
I want to find products on basis of this sku name's first two words.
I am creating shortcode for this purpose, but can't able to get it work.
Any help should be appreciated.
Code for this shortcode:
function all_state_list_function(){
$name = $_GET['sku']; //this give sku value from url like Al:2323
echo $name;
$args = array(
'post_type' => 'product',
'posts_per_page' => -1,
'orderby' => 'name',
'order' => 'DESC',
'meta_query' => array(
'relation' => 'AND',
array(
'key' => 'free_form',
'value' => '1',
),
array(
'key' => '_sku',
'value' => $name.'-%',
'compare' => 'LIKE',
),
),
);
$loop = new WP_Query( $args );
while ( $loop->have_posts() ) : $loop->the_post();
$product_id = get_the_ID();
echo $product_id;
endwhile;
wp_reset_query();
}
add_shortcode( 'all_state_list_shortcode', 'all_state_list_function' );
Based on your first version code that had an SQL query, here is the correct way to get product IDs from first SKU characters value using GET method from an URL:
add_shortcode( 'all_state_list_shortcode', 'all_state_list_function' );
function all_state_list_function(){
if ( isset($_GET['sku']) && ! empty($_GET['sku']) ) {
ob_start();
$sku = esc_attr( $_GET['sku'] ) .'%';
global $wpdb;
$results = $wpdb->get_col( "
SELECT p.ID FROM {$wpdb->prefix}posts as p
JOIN {$wpdb->prefix}postmeta as pm ON p.ID = pm.post_id
WHERE p.post_type LIKE 'product' AND p.post_status LIKE 'publish'
AND meta_key LIKE '_sku' AND meta_value LIKE '$sku'
" );
if( count($results) > 0 ) {
echo implode(',', $results);
} else {
echo 'Nothing found';
}
return ob_get_clean();
}
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
I have been trying for a couple of hours to make this work - but for some reason its simply to difficult for me. I have a custom post_type 'house', and I want to find the post_id of my custom post_type with a meta_key and certain meta value.
Lets say i want to find post_id for a house with
meta_key='house_id'
meta_value='231sd1223'
How exactly would i do that with wp->query?
Here you have the query even with a loop. However, querying meta values is making more DB queries, consider looping throught "house" post type and than doing something only if meta_value is equal the house number.
// WP_Query arguments
$args = array (
'post_type' => array( 'house' ),
'post_status' => array( 'publish' ),
'meta_query' => array(
array(
'key' => 'house_id',
'value' => '231sd1223',
),
),
);
// The Query
$query = new WP_Query( $args );
// The Loop
if ( $query->have_posts() ) {
while ( $query->have_posts() ) {
$query->the_post();
// do something
}
} else {
// no posts found
}
// Restore original Post Data
wp_reset_postdata();
global $wpdb;
$results = $wpdb->get_results( "select post_id, meta_key from $wpdb->postmeta where meta_value = '231sd1223.'", ARRAY_A );
I've been trying to create a custom search query, and I've made some progress on it, but have hit another roadbump.
I'm trying to combine the meta_query, keyword search ('s') and tax_query in a wp_query with an 'OR' relationship.
I've gotten the meta_query and 's' to work together thanks to this fantastic post:
https://wordpress.stackexchange.com/questions/99849/search-that-will-look-in-custom-field-post-title-and-post-content
however, the tax_query is still giving me trouble. I tried adding it in via the same method, but it seems as though wordpress does some other magic with tax_query before it outputs it to the SQL query.
Here's what I've got thus far:
function add_join_wpse_news($joins)
{
global $wpdb;
return $joins . " INNER JOIN {$wpdb->postmeta} ON ({$wpdb->posts}.ID = {$wpdb->postmeta}.post_id)" ;
}
function alter_search_wpse_news($search,$qry)
{
global $wpdb;
$add = $wpdb->prepare("({$wpdb->postmeta}.meta_key = '_et_builder_settings' AND CAST({$wpdb->postmeta}.meta_value AS CHAR) LIKE '%%%s%%')",$qry->get('s'));
$pat = '|\(\((.+)\)\)|';
$search = preg_replace($pat,'(($1 OR '.$add.'))',$search);
return $search;
}
function alter_groupby_wpse_news($groupby)
{
global $wpdb;
$mygroupby = "{$wpdb->posts}.ID";
if( preg_match( "/$mygroupby/", $groupby )) {
// grouping we need is already there
return $groupby;
}
if( !strlen(trim($groupby))) {
// groupby was empty, use ours
return $mygroupby;
}
// wasn't empty, append ours
return $groupby . ", " . $mygroupby;
}
add_filter('posts_join','add_join_wpse_news');
add_filter('posts_search','alter_search_wpse_news',1,2);
add_filter('posts_groupby', 'alter_groupby_wpse_news' );
$args_condensed = array
(
'post_type' => 'news',
'paged' => $paged,
's' => $getname,
);
$the_query = new WP_Query($args_condensed);
$max_pages = $the_query->max_num_pages;
echo $GLOBALS['the_query']->request;
And this works. However, it doesn't include the search for the the Tags or Categories. I attempted to add it in manually via the posts_join and posts_search filter, but then I realized that wordpress is comparining values in the tax_query BEFORE the outputted SQL query, which causes problems when trying to add it in.
Any help would be greatly appreciated.
EDIT: for clarification, I'm trying to add in:
'tax_query' => array
(
'relation' => 'OR',
array //Search Tag
(
'taxonomy' => 'post_tag',
'field' => 'slug',
'terms' => array($getname)
),
array //Search Category
(
'taxonomy' => 'category',
'field' => 'slug',
'terms' => array($getname),
),
array //Search Category (Single Words)
(
'taxonomy' => 'category',
'field' => 'slug',
'terms' => explode(" ",$getname),
),
array //Search Tag (Single Words)
(
'taxonomy' => 'post_tag',
'field' => 'slug',
'terms' => explode(" ",$getname),
)
),
but with an OR type relationship as opposed to the AND relationship wordpress adds by default.
There are no way you can use tax_query for this purpose. You must override filter that wordpress provided to achieve this mission. Here is my code. Hope it help:
function add_join_wpse_news($joins)
{
global $wpdb;
$joins = $joins . " INNER JOIN {$wpdb->postmeta} ON ({$wpdb->posts}.ID = {$wpdb->postmeta}.post_id)" ;
$joins .= " inner join {$wpdb->term_relationships} as wrel on {$wpdb->posts}.ID = wrel.object_id";
$joins .= " inner join {$wpdb->term_taxonomy} as wtax on wtax.term_taxonomy_id = wrel.term_taxonomy_id";
$joins .= " inner join {$wpdb->terms} as wter on wter.term_id = wtax.term_id";
return $joins;
}
function add_where_wpse_news($where) {
$getname = 'what you want';
return $where. ' AND '. "wter.slug like '%$getname%' ";
}
add_filter('posts_join','add_join_wpse_news');
add_filter('posts_where','add_where_wpse_news');
I just add posts_where and modify posts_join filter.
I'm trying to filter my posts to only show the ones with that have a custom value for the field "Model" while sorting the posts by another custom field called "Price."
Here's the function I'm using (not working):
<?php
global $query_string;
query_posts( $query_string . "&meta_value=Model&orderby=meta_value&meta_key=Price&order=ASC");
?>
This function only shows Models, yet doesn't sort the posts by Price. If i add &meta_value=Model after order=ASC it sorts by Price but shows all posts, and not just Models.
Have you looked at http://codex.wordpress.org/Class_Reference/WP_Query
Specifically this section:
Multiple Custom Field Handling:
Display posts from several custom field:
$args = array(
'post_type' => 'product',
'meta_query' => array(
array(
'key' => 'color',
'value' => 'blue',
'compare' => 'NOT LIKE'
),
array(
'key' => 'price',
'value' => array( 20, 100 ),
'type' => 'numeric',
'compare' => 'BETWEEN'
)
)
);
$query = new WP_Query( $args );
did you try and array?
$args = array(
'meta_value' => array('Model','Price')
);
query_posts($args);
I know this is an old question, but I needed the answer today and couldn't find it anywhere. I found the question and then created an answer (shown below):
<?php
$sql = "
SELECT ID, meta1.meta_value, meta2.meta_value from $wpdb->posts p
JOIN $wpdb->postmeta meta1 ON meta1.post_id = p.ID
JOIN $wpdb->postmeta meta2 ON meta2.post_id = p.ID
WHERE p.post_status = 'publish'
AND p.post_type = 'post'
AND meta1.meta_key = 'Model'
AND meta2.meta_key = 'Price'
ORDER BY meta2.meta_value DESC
";
$posts_with_meta = $wpdb->get_col($sql);
$my_query = new WP_Query();
foreach ($posts_with_meta as $p) {
$post = get_post(intval($p));
setup_postdata($post);
print_r($post);
}
?>