I try create search in wordpress not only by titles and content but also by meta fields.
So I wrote in functions.php:
function custom_search_query( $query ) {
if ( !is_admin() && $query->is_search ) {
$query->set('meta_query', array(
'relation' => 'OR',
array(
'key' => 'country_name_work',
'value' => $query->query_vars['s'],
'compare' => 'LIKE'
)
));
$query_vars = $query->query_vars;
$query_vars['relation'] = 'OR';
};
}
add_filter( 'pre_get_posts', 'custom_search_query');
The result SQL by search field Poland is:
SELECT SQL_CALC_FOUND_ROWS wp_posts.ID FROM wp_posts INNER JOIN wp_postmeta ON ( wp_posts.ID = wp_postmeta.post_id ) WHERE 1=1 AND wp_posts.ID NOT IN (2,5,12,14,20) AND (((wp_posts.post_title LIKE '%poland%') OR (wp_posts.post_content LIKE '%poland%'))) **AND** (
( wp_postmeta.meta_key = 'country_name_work' AND CAST(wp_postmeta.meta_value AS CHAR) LIKE '%poland%' )
) AND wp_posts.post_type IN ('post', 'page', 'attachment', 'jobs') AND (wp_posts.post_status = 'publish' OR wp_posts.post_author = 1 AND wp_posts.post_status = 'private') GROUP BY wp_posts.ID ORDER BY wp_posts.post_title LIKE '%poland%' DESC, wp_posts.post_date DESC LIMIT 0, 40
It would work fine if the query would be:
SELECT SQL_CALC_FOUND_ROWS wp_posts.ID FROM wp_posts INNER JOIN wp_postmeta ON ( wp_posts.ID = wp_postmeta.post_id ) WHERE 1=1 AND wp_posts.ID NOT IN (2,5,12,14,20) AND (((wp_posts.post_title LIKE '%poland%') OR (wp_posts.post_content LIKE '%poland%'))) **OR** (
( wp_postmeta.meta_key = 'country_name_work' AND CAST(wp_postmeta.meta_value AS CHAR) LIKE '%poland%' )
) AND wp_posts.post_type IN ('post', 'page', 'attachment', 'jobs') AND (wp_posts.post_status = 'publish' OR wp_posts.post_author = 1 AND wp_posts.post_status = 'private') GROUP BY wp_posts.ID ORDER BY wp_posts.post_title LIKE '%poland%' DESC, wp_posts.post_date DESC LIMIT 0, 40
Operator AND should be OR.
I tried these suggestions -
meta_query, how to search using both relation OR & AND?
and
https://wordpress.stackexchange.com/questions/104060/using-or-conditions-in-meta-query-for-query-posts-argument - but it is not working correctly.
Updated:
Now I introduce answer of doublesharp. But I have issue again.
Now my code look like:
function post_title_filter( $where, &$query ){
global $wpdb;
if ( $post_title = $query->get( 'post_title' ) ){
$post_title = $wpdb->esc_like( $post_title );
$post_title = " '%{$post_title}%'";
$title_filter_relation = strtoupper( $query->get( 'post_title_relation' ) ) == 'OR' ? 'OR' : 'AND';
$where .= " {$title_filter_relation} {$wpdb->posts}.post_title LIKE {$post_title}";
}
return $where;
}
function post_content_filter( $where, &$query ){
global $wpdb;
if ( $post_content = $query->get( 'post_content' ) ){
$post_content = $wpdb->esc_like( $post_content );
$post_content = " '%{$post_content}%'";
$content_filter_relation = strtoupper( $query->get( 'post_content_relation' ) ) == 'OR' ? 'OR' : 'AND';
$where .= " {$content_filter_relation} {$wpdb->posts}.post_content LIKE {$post_content}";
}
return $where;
}
add_filter( 'posts_where', 'post_title_filter', 10, 2 );
add_filter( 'posts_where', 'post_content_filter', 10, 2 );
function custom_search_query( $query ) {
if ( !is_admin() && $query->is_search) {
//$query->is_search=false;
$query->is_search1=true;
$search = $query->query_vars['s'];
$query->set( 'post_title', $search );
$query->set( 'post_title_relation', 'OR' );
$query->set( 'post_content', $search );
$query->set( 'post_content_relation', 'OR' );
$query->set( 'meta_query', array(
'relation'=>'OR',
array(
'key' => 'country_name_work',
'value' => $query->query_vars['s'],
'compare' => 'LIKE'
),array(
'key' => 'sex',
'value' => $query->query_vars['s'],
'compare' => 'LIKE'
),array(
'key' => 'status',
'value' => $query->query_vars['s'],
'compare' => 'LIKE'
),array(
'key' => 'age-from',
'value' => $query->query_vars['s'],
'compare' => 'LIKE'
),array(
'key' => 'age-to',
'value' => $query->query_vars['s'],
'compare' => 'LIKE'
),array(
'key' => 'exp',
'value' => $query->query_vars['s'],
'compare' => 'LIKE'
),array(
'key' => 'work-env',
'value' => $query->query_vars['s'],
'compare' => 'LIKE'
),array(
'key' => 'work-conditions',
'value' => $query->query_vars['s'],
'compare' => 'LIKE'
),array(
'key' => 'schedule',
'value' => $query->query_vars['s'],
'compare' => 'LIKE'
),array(
'key' => 'salary',
'value' => $query->query_vars['s'],
'compare' => 'LIKE'
)
));
}
}
add_filter( 'pre_get_posts', 'custom_search_query' );
And generated query looks:
SELECT SQL_CALC_FOUND_ROWS wp_posts.ID FROM wp_posts INNER JOIN wp_postmeta ON ( wp_posts.ID = wp_postmeta.post_id ) WHERE 1=1 AND (((wp_posts.post_title LIKE '%poland%') OR (wp_posts.post_content LIKE '%poland%'))) AND (wp_posts.post_password = '') AND ( ( wp_postmeta.meta_key = 'country_name_work' AND CAST(wp_postmeta.meta_value AS CHAR) LIKE '%poland%' ) OR ( wp_postmeta.meta_key = 'sex' AND CAST(wp_postmeta.meta_value AS CHAR) LIKE '%poland%' ) OR ( wp_postmeta.meta_key = 'status' AND CAST(wp_postmeta.meta_value AS CHAR) LIKE '%poland%' ) OR ( wp_postmeta.meta_key = 'age-from' AND CAST(wp_postmeta.meta_value AS CHAR) LIKE '%poland%' ) OR ( wp_postmeta.meta_key = 'age-to' AND CAST(wp_postmeta.meta_value AS CHAR) LIKE '%poland%' ) OR ( wp_postmeta.meta_key = 'exp' AND CAST(wp_postmeta.meta_value AS CHAR) LIKE '%poland%' ) OR ( wp_postmeta.meta_key = 'work-env' AND CAST(wp_postmeta.meta_value AS CHAR) LIKE '%poland%' ) OR ( wp_postmeta.meta_key = 'work-conditions' AND CAST(wp_postmeta.meta_value AS CHAR) LIKE '%poland%' ) OR ( wp_postmeta.meta_key = 'schedule' AND CAST(wp_postmeta.meta_value AS CHAR) LIKE '%poland%' ) OR ( wp_postmeta.meta_key = 'salary' AND CAST(wp_postmeta.meta_value AS CHAR) LIKE '%poland%' ) ) AND wp_posts.post_type IN ('post', 'page', 'attachment', 'jobs') AND (wp_posts.post_status = 'publish') OR wp_posts.post_title LIKE '%poland%' OR wp_posts.post_content LIKE '%poland%' GROUP BY wp_posts.ID ORDER BY wp_posts.post_title LIKE '%poland%' DESC, wp_posts.post_date DESC LIMIT 0, 40
You will need to use the posts_where filter to add to the WHERE statement that is generated by WP_Query. This example adds two additional arguments - post_title and post_title_relation to allow you to where the title is LIKE a value OR there is a meta_key with that value.
Use the posts_where and pre_get_posts filters
function post_title_filter( $where, &$query ){
global $wpdb;
if ( $post_title = $query->get( 'post_title' ) ){
$post_title = $wpdb->esc_like( $post_title );
$post_title = " '%{$post_title}%'";
$title_filter_relation = strtoupper( $query->get( 'post_title_relation' ) ) == 'OR' ? 'OR' : 'AND';
$where .= " {$title_filter_relation} {$wpdb->posts}.post_title LIKE {$post_title}";
}
return $where;
}
add_filter( 'posts_where', 'post_title_filter', 10, 2 );
function custom_search_query( $query ) {
if ( !is_admin() && $query->is_search ) {
$search = $query->query_vars['s'];
$query->set( 'post_title', $search );
$query->set( 'post_title_relation', 'OR' );
$query->set( 'meta_query', array(
array(
'key' => 'country_name_work',
'value' => $query->query_vars['s'],
'compare' => 'LIKE'
)
));
}
}
add_filter( 'pre_get_posts', 'custom_search_query' );
Example using WP_Query directly
$search = 'test';
$args = array(
'post_title' => $search,
'post_title_relation' => 'OR',
'meta_query' => array(
array(
'key' => 'test',
'value' => $search,
'compare' => 'LIKE'
)
)
);
$query = new WP_Query( $args );
Related
I need to make changes to the code that calculates prices for a large number of variants of one product according to the set price calculation logic
How to change the code below to:
all variants in white would have a price calculated according to "$price1 = round (... calculations ...);.
and variants in black would have a price calculated according to $price2 = round (... calculations ...);
<?php
(...)
$config = [
'product_id' => 123,
'attributes_values' => [
(...)
'attribute_pa_color' => [
'white' => 1,
'black' => 2,
]
]
];
$product_variations = $wpdb->get_results("SELECT * FROM `wp_posts` WHERE `post_parent` = ".$config['product_id']." AND `post_type` LIKE 'product_variation'");
if( $product_variations ){
foreach( $product_variations as $product_variation ){
$pva = [];
$product_variation_attributes_dba = $wpdb->get_results("SELECT * FROM `wp_postmeta` WHERE `post_id` = ".$product_variation->ID." AND `meta_key` LIKE 'attribute_pa_%'");
if ( $product_variation_attributes_dba ) foreach( $product_variation_attributes_dba as $prod_attr){
$value = $config['attributes_values'][$prod_attr->meta_key][$prod_attr->meta_value];
if( !empty( $config['attributes_values'][$prod_attr->meta_key] ) ){
if( !$value>0 ){
echo 'Błąd przy parsowaniu produktu #'.$product_variation->ID.' ('.$prod_attr->meta_key.' = '.$prod_attr->meta_value.')<br>';
exit;
}
$pva[ $prod_attr->meta_key ] = $value;
}
}
$price1 = round( ...calculations... );
$price2 = round( ...calculations... );
$regular_price = $wpdb->get_row("SELECT * FROM `wp_postmeta` WHERE `post_id` = ".$product_variation->ID." AND `meta_key` LIKE '_regular_price'");
if($regular_price){
$wpdb->update( 'wp_postmeta', array( 'meta_value'=> $price ), array( 'post_id' => $product_variation->ID, 'meta_key' => '_regular_price' ) ,array( '%s', '%s', '%d', ) );
}else{
$wpdb->insert( 'wp_postmeta', array( 'post_id' => $product_variation->ID, 'meta_key' => '_regular_price', 'meta_value'=> $price ), array( '%s', '%s', '%d', ) );
}
$regular_price = $wpdb->get_row("SELECT * FROM `wp_postmeta` WHERE `post_id` = ".$product_variation->ID." AND `meta_key` LIKE '_price'");
if($regular_price){
$wpdb->update( 'wp_postmeta', array( 'meta_value'=> $price ), array( 'post_id' => $product_variation->ID, 'meta_key' => '_price' ) ,array( '%s', '%s', '%d', ) );
}else{
$wpdb->insert( 'wp_postmeta', array( 'post_id' => $product_variation->ID, 'meta_key' => '_price', 'meta_value'=> $price ), array( '%s', '%s', '%d', ) );
}
$_thumbnail_id = $pva['attribute_pa_color']==2?4333:4278;
$wpdb->update( 'wp_postmeta', array( 'meta_value'=> $_thumbnail_id ), array( 'post_id' => $product_variation->ID, 'meta_key' => '_thumbnail_id' ) ,array( '%s', '%s', '%d', ) );
}
}
echo 'Successful price import!';
I have a meta_query like this:
$meta_query_args = array(
'relation' => 'AND',
array(
'key' => 'apartment-price',
'value' => array(50000, 100000),
'compare' => 'BETWEEN',
'type' => 'numeric'
),
array(
'key' => 'apartment-block',
'value' => $data['block'],
'compare' => 'IN'
),
array(
'key' => 'apartment-floor',
'value' => intval($data['floor']),
'compare' => 'IN',
'type' => 'numeric'
)
);
$meta_query = new WP_Query(
array(
'post_type' => 'apartment',
'meta_query' => $meta_query_args
)
);
And I want to filter apartment-price between 50000 and 100000, but I get query like this:
SELECT SQL_CALC_FOUND_ROWS wp_posts.ID FROM wp_posts INNER JOIN wp_postmeta ON ( wp_posts.ID = wp_postmeta.post_id ) INNER JOIN wp_postmeta AS mt1 ON ( wp_posts.ID = mt1.post_id ) INNER JOIN wp_postmeta AS mt2 ON ( wp_posts.ID = mt2.post_id ) WHERE 1=1 AND (
( wp_postmeta.meta_key = 'apartment-price' AND CAST(wp_postmeta.meta_value AS SIGNED) BETWEEN '50000' AND '100000' )
AND
( mt1.meta_key = 'apartment-block' AND mt1.meta_value IN ('B') )
AND
( mt2.meta_key = 'apartment-floor' AND CAST(mt2.meta_value AS SIGNED) IN ('1') )
) AND wp_posts.post_type = 'apartment' AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'future' OR wp_posts.post_status = 'draft' OR wp_posts.post_status = 'pending') GROUP BY wp_posts.ID ORDER BY wp_posts.post_date DESC LIMIT 0, 10
So it doesn't work because the numbers have been quoted. Why parameter 'type' is not working? Help please!
BTW apartment-floor filter is not working too, same reason.
I have area (lat0, lat1, lng0, lng1). Why my wp_query not working?
$new_query->query( array(
'post_type' => 'object',
'meta_query' => array(
array(
'relation' => 'AND',
array(
'key' => 'lat',
'compare' => 'BETWEEN',
'value' => array($lat0, $lat1),
'type' => 'DECIMAL',
),
array(
'key' => 'lng',
'compare' => 'BETWEEN',
'value' => array($lng0, $lng1),
'type' => 'DECIMAL',
)
),
),
)
);
I get some result if I use:
array(
'key' => 'lat',
'compare' => '<=',
'value' => $lat0,
'type' => 'DECIMAL',
),
But this code not working:
array(
'relation' => 'AND',
array(
'key' => 'lat',
'compare' => '>=',
'value' => $lat0,
'type' => 'DECIMAL',
),
array(
'key' => 'lat',
'compare' => '<=',
'value' => $lat1,
'type' => 'DECIMAL',
)
),
Can I use wp_query for search by area. And if this wrong way, what I can do?
Fixed
global $wpdb;
$querystr = "
SELECT *
FROM $wpdb->posts
INNER JOIN $wpdb->postmeta m1
ON ( $wpdb->posts.ID = m1.post_id )
INNER JOIN $wpdb->postmeta m2
ON ( $wpdb->posts.ID = m2.post_id )
INNER JOIN $wpdb->postmeta m3
ON ( $wpdb->posts.ID = m3.post_id )
WHERE
$wpdb->posts.post_type = 'object'
AND $wpdb->posts.post_status = 'publish'
AND ( m1.meta_key = 'lat' AND m1.meta_value < $lat0 )
AND ( m1.meta_key = 'lat' AND m1.meta_value > $lat1 )
AND ( m2.meta_key = 'lng' AND m2.meta_value < $lng0 )
AND ( m2.meta_key = 'lng' AND m2.meta_value > $lng1 )
AND ( m3.meta_key = 'city' AND m3.meta_value = $city_string )
GROUP BY $wpdb->posts.ID
ORDER BY $wpdb->posts.post_date
DESC;
";
$pageposts = $wpdb->get_results($querystr, OBJECT);
I want to get minimum price and maximum price based on categories.
The woocommerce query which gives me minimum and maximum product price range but i want it on the bases of category.
for example: category="music,clothing".
Here is query for minimum and maximum price:
$min = floor( $wpdb->get_var(
$wpdb->prepare('
SELECT min(meta_value + 0)
FROM %1$s
LEFT JOIN %2$s ON %1$s.ID = %2$s.post_id
WHERE meta_key IN ("' . implode( '","', apply_filters( 'woocommerce_price_filter_meta_keys', array( '_price', '_min_variation_price' ) ) ) . '")
AND meta_value != ""
', $wpdb->posts, $wpdb->postmeta )
) );
$max = ceil( $wpdb->get_var(
$wpdb->prepare('
SELECT max(meta_value + 0)
FROM %1$s
LEFT JOIN %2$s ON %1$s.ID = %2$s.post_id
WHERE meta_key IN ("' . implode( '","', apply_filters( 'woocommerce_price_filter_meta_keys', array( '_price' ) ) ) . '")
', $wpdb->posts, $wpdb->postmeta, '_price' )
) );
Please suggest me how can i get it according to category selected.
SQL Query:
//SQL Query to get max price :
SELECT max(meta_value + 0) FROM wp_posts LEFT JOIN wp_postmeta ON wp_posts.ID = wp_postmeta.post_id INNER JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id) WHERE meta_key = '_price' AND (wp_term_relationships.term_taxonomy_id IN (46,47));
//SQL Query to get min price :
SELECT min(meta_value + 0) FROM wp_posts LEFT JOIN wp_postmeta ON wp_posts.ID = wp_postmeta.post_id INNER JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id) WHERE (meta_key = '_price' OR meta_key='_min_variation_price') AND (wp_term_relationships.term_taxonomy_id IN (46,47));
//46, 47 is the term id of category. So you need to have id of music and clothing
WP_Query :
This is the way how I do it :
<?php
$category = array('t-shirt');
$args = array(
'posts_per_page' => -1,
'post_type' => 'product',
'orderby' => 'meta_value_num',
'order' => 'DESC',
'tax_query' => array(
array(
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => $category,
'operator' => 'IN'
)
),
'meta_query' => array(
array(
'key' => '_price',
)
)
);
$loop = new WP_Query($args);
echo "Max :" get_post_meta($loop->posts[0]->ID, '_price', true);
?>
I used 'order'=>'DESC' so that it will sort by Highest to Lower and hence we can get Highest from it.
If you want to have Min, change 'order'=>'DESC' to 'order'=>'ASC' and you will have echo "Min :" get_post_meta($loop->posts[0]->ID, '_price', true);
Rohil_PHPBeginner's answer is correct, but you do no need to get prices for all products to find the maximum. You can just alter the "posts_per_page" to be 1:
<?php
$category = array('t-shirt');
$args = array(
'posts_per_page' => 1,
'post_type' => 'product',
'orderby' => 'meta_value_num',
'order' => 'DESC',
'tax_query' => array(
array(
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => $category,
'operator' => 'IN'
)
),
'meta_query' => array(
array(
'key' => '_price',
)
)
);
$loop = new WP_Query($args);
echo "Max :" get_post_meta($loop->posts[0]->ID, '_price', true);
wp_reset_postdata();
?>
i have posts with two advanced custom fields "name" and "surname"
and i need to query the post to have it in the right sequece.
name / surnname / title
like this:
Doe, Joen, Title
my query looks like this
$args = array(
'numberposts' => -1,
'post_type' => array ('events'),
'meta_key' => 'name',
'orderby' => 'meta_value',
'order' => 'ASC',
'meta_query'=> array(
array(
'key' => 'date',
'compare' => '<',
'value' => $today,
'type' => 'DATE',
)),
);
How can I order the posts in the right way?
i tried something like this:
'orderby' => 'meta_value surname',
but i think this dont work with custom fields
thanks!!!
++
thanks alot Mukesh!
this works (i hope so…)
SELECT SQL_CALC_FOUND_ROWS * FROM wpdev_posts
INNER JOIN wpdev_postmeta ON ( wpdev_posts.ID = post_id )
INNER JOIN wpdev_postmeta AS mt1 ON ( wpdev_posts.ID = mt1.post_id )
INNER JOIN wpdev_postmeta AS mt2 ON ( wpdev_posts.ID = mt2.post_id )
WHERE 1=1 AND ( wpdev_postmeta.meta_key = 'referent_name' ) AND ( mt1.meta_key = 'referent_vorname' )
AND ( ( mt2.meta_key = 'datum' AND CAST(mt2.meta_value AS DATE) < 20190527 ) )
AND wpdev_posts.post_type = 'veranstaltungen'
AND (wpdev_posts.post_status = 'publish'
OR wpdev_posts.post_status = 'pending' OR wpdev_posts.post_status = 'confirmed'
OR wpdev_posts.post_status = 'paid' OR wpdev_posts.post_status = 'complete'
OR wpdev_posts.post_status = 'private')
GROUP BY wpdev_posts.ID
ORDER BY wpdev_postmeta.meta_value ASC, mt1.meta_value ASC, post_title ASC
Try below code it will help to you.
<?php
global $wpdb;
$query = "SELECT SQL_CALC_FOUND_ROWS * FROM $wpdb->posts
INNER JOIN $wpdb->postmeta ON ( $wpdb->posts.ID = $wpdb->postmeta.post_id )
INNER JOIN $wpdb->postmeta AS mt1 ON ( wp_posts.ID = mt12.post_id )
INNER JOIN $wpdb->postmeta AS mt2 ON ( wp_posts.ID = mt2.post_id )
WHERE 1=1 AND ( $wpdb->postmeta.meta_key = 'name' ) AND ( mt1.meta_key = 'surname' )
AND ( ( mt2.meta_key = 'date' AND CAST(mt2.meta_value AS DATE) < $today ) ) )
AND $wpdb->posts.post_type = 'events' AND ($wpdb->posts.post_status = 'publish'
OR $wpdb->posts.post_status = 'pending' OR $wpdb->posts.post_status = 'confirmed'
OR $wpdb->posts.post_status = 'paid' OR $wpdb->posts.post_status = 'complete'
OR $wpdb->posts.post_status = 'private')
GROUP BY wp_posts.ID
ORDER BY wp_postmeta.meta_value ASC, mt1.meta_value ASC ";
$posts = $wpdb->get_results($query, object);
echo '<pre>';print_r($posts);
?>