I have a custom post type of post_type_1 in WordPress, I also have a custom field in that post type of custom_field_data
I am doing a search for apples by querying posts using wp_query like this...
$search_term = 'apples';
$args = array(
'post_type' => array('post_type_1'),
'post_status' => array('publish'),
'posts_per_page' => -1,
's' => sanitize_text_field( $search_term)
);
$results= new WP_Query( $args );
This works correctly and returns all posts with apples in the title, but I would also like to extend the search to the custom field custom_field_data so the query will return all posts with apples in either title or custom field.
What is my best approach? I have tried using a meta_query but haven't been successful. Does anybody have an example?
Use below code will work for custom field search.
$custom_field = $_GET['custom_field '] != '' ? $_GET['custom_field '] : '';
$search_term = 'apples';
$args = array(
'post_type' => array('post_type_1'),
'post_status' => array('publish'),
'posts_per_page' => -1,
's' => sanitize_text_field( $search_term),
'meta_query' => array(
array(
'key' => 'custom_field_key',
'value' => $custom_field ,
'compare' => 'LIKE',
),
)
);
$results= new WP_Query( $args );
Tested and works well.
Related
I am trying to do a query my wocommerce products by their variations, so I did:
$args = array(
'meta_key' => 'flower-type', // attribute slug
'meta_value' => 'fresh-roses', // attribute value
'meta_compare' => 'LIKE'
);
$the_query = new WP_Query( $args );
if ( $the_query->have_posts() ) :
while ( $the_query->have_posts() ) : $the_query->the_post();
wc_get_template_part( 'content', 'product' );
endwhile;
wp_reset_postdata();
else :
_e( 'Sorry, no posts matched your criteria.' );
endif;
but unfortunately I always get no results, so what is the issue here?
This type of data is saved in a dynamic created meta key so the attribute name counts when making the query, in your case I assumed the slug for your attribute name is "flower-type", you can check this in your database to confirm.
The meta key that you want to use is compose out of the word attribute and the name of the attribute you created when making the variations fresh-flowers in your case.
Be careful that changing this in the admin will "break" your query.
So the arguments will look like:
$args = array(
'post_type' => 'product',
'orderby' => 'meta_value_num',
'order' => 'DESC',
'meta_query' => array(
array(
'key' => 'attribute_flower-type',
'value' => 'fresh-roses',
'compare' => 'LIKE',
),
),
);
please notice the compare attribute used, it might work with = but first confirm that it works with LIKE and then you can play with it.
Try below argument for passing into WP query:
args = array(
'post_type' => 'product',
'orderby' => 'meta_value_num',
'order' => 'DESC',
'meta_query' => array(
array(
'key' => 'flower-type',
'value' => 'fresh-roses',
'compare' => '=',
),
),
);
in short I have the following situation: products that are posted by the users which have a custom post type. Call them "ads". Ads have a 1-1 link to WooCommerce Products.
Next to that I have WooCommerce Products that are Vendor Item (they are added by a multiple vendor plugin) and distinguish from other post_type products with their meta_key "_vendor_product" set to 1.
So far I made 2 queries and added them:
$ads = new WP_Query(
array(
'post_type' => 'ads',
'paged' => $paged,
'post_status' => 'publish',
'meta_query' => array(
array(
'key' => 'product_id',
'value' => $product_ids,
'compare' => 'IN'
)
)
)
);
$shop_items = new WP_Query(
array(
'post_type' => 'product',
'paged' => $paged,
'post__in' => $product_ids,
'meta_query' => array(
array(
'key' => '_vendor_product',
'value' => 1,
'compare' => '='
)
)
)
);
}
// Include shop items in the stream of products
$wp_query = new WP_Query(array('paged' => $paged));
$wp_query->posts = array_merge( $ads->posts, $shop_items->posts );
$wp_query->post_count = $ads->post_count + $shop_items->post_count;
But I need them both in one WP_Query, as otherwise somehwere my actions/filters/pagination seem to break.
I know I can query different post_types by 'post_type' => array( 'ads', 'product' ) but the condition of _vendor_product = 1 only applies to the items of post_type product and not to ads.
What I need is basically
SELECT * FROM wp_posts, wp_postmeta
WHERE (post_type = 'ads')
OR
(post_type = 'product' AND meta_key = '_vendor_product' AND meta_value = 1)
AND
wp_posts.ID = wp_postmeta.post_id
Is it possible to achieve this within the boundaries of WP_Query?
I achieved my result basically the same way Blackbam suggested, although without directly involving SQL.
If anyone ever finds this I will post my solution as it gave me a bit of a headache to figure out why my results were limited to 10 when using get_posts on WP_Query (the solution was 'nopaging' in WP_Query.
$ps_ads = new WP_Query(
array(
'post_type' => 'ads',
'fields' => 'ids',
'nopaging' => true,
'post_status' => 'publish'
)
);
$shop_items = new WP_Query(
array(
'post_type' => 'product',
'fields' => 'ids',
'nopaging' => true,
'post__in' => $product_ids,
'meta_query' => array(
array(
'key' => '_vendor_product',
'value' => 1,
'compare' => '='
)
)
)
);
}
// Sum up all IDs
$ad_ids = $ps_ads->get_posts();
$shop_items_ids = $shop_items->get_posts();
$ids = array_merge($ad_ids, $shop_items_ids);
$wp_query = new WP_Query(
array(
'post_type' => array( 'ads' , 'product' ),
'paged' => $paged,
'post__in' => $ids
)
);
Hope it helps.
I doubt that you can achieve it within one query directly (however somebody may bring up a solution). However I suggest an easy workaround to this problem - find out the post IDs and make a single query from that:
global $wpdb;
$all_needed = $wpdb->get_results('SELECT wp_posts.id FROM wp_posts, wp_postmeta
WHERE (post_type = 'ads')
OR
(post_type = 'product' AND meta_key = '_vendor_product' AND meta_value = 1)
AND
wp_posts.ID = wp_postmeta.post_id');
// extract_ids is a pseudo-code function - check what the result actually is and make an array of post_ids
$post_ids = extract_ids($all_needed)
// now you have your single query
$query = new WP_Query(array('post__in'=>$post_ids));
// proceed ....
I'm using the advanced custom fields plugin for wordpress to create a group of custom post types that have a date set within them.
I'm trying to show the previous post, and the next post, based on the date stored in the custom field. The links need to link to posts that have a date set in the future (so don't show links to posts with dates that have gone by)/
I can get a list of all the posts that are in the future, and out put these using the following code;
<?php
$rightnow = current_time('Ymd');
$args = array(
'post_type' => 'Courses',
'posts_per_page' => '25',
'meta_query' => array(
array(
'key' => 'date_of_the_course_single_day',
'compare' => '>=',
'value' => $rightnow,
)
),
'meta_key' => 'date_of_the_course_single_day',
'orderby' => 'meta_value',
'order' => 'ASC',
'post_status' => 'publish'
);
$posts = get_posts($args);
foreach ( $posts as $post ) {
?>
Output details of post here....
<?php
}
?>
What I thought I could do, is the get the current post's position in the array, to then get details of the posts one before and one after... but I haven't got a clue how to do this.
I've experimented with the wordpress next_post_link and previous_post_link functions, but these seem to work based on when the post was added to wordpress, rather than based on my custom date field.
Am I going about this the complete wrong way? Any tips or pointers would be much appreciated!
Use WP_Query plus paginate_links
$rightnow = current_time('Ymd');
// Query Args
$args = array(
'post_type' => 'Courses',
'posts_per_page' => '25',
'meta_query' => array( array(
'key' => 'date_of_the_course_single_day',
'compare' => '>=',
'value' => $rightnow,
) ),
'meta_key' => 'date_of_the_course_single_day',
'orderby' => 'meta_value',
'order' => 'ASC',
'post_status' => 'publish'
);
$query = new WP_QUery( $arg );
$posts = $query->get_posts();
// Paginate Args
$page_args = array(
'base' => 'your_custom_page_url'.'%_%', // Make sure you got this current depending on your setup
'format' => '/%#%', // requires pretty permalinks
'total' => $query->max_num_pages,
'current' => 0,
'prev_text' => __('«'),
'next_text' => __('»'),
);
foreach ( $posts as $post ) {
// Output
}
echo paginate_links( $page_args );
You have to verify that the base and format of paginate args are correct of it won't properly worked.
This one's driving me nuts.. I'm trying to query and output WooCommerce products based on a specific attribute. For example, I set up an Attribute called on, with possible values of yes or no.
I query using the following:
$args = array(
'post_type' => 'product',
'meta_key' => 'pa_on',
'meta_value' => 'yes',
'posts_per_page' => -1
);
query_posts($args);
The meta_key is crucial perhaps; if I call it on I get nothing. If I call it pa_on (because that's how I understand WooCommerce custom attributes to be constructed) I get nothing.
However, if I try a different query and use _featured, which is a standard WooCommerce custom meta thingy, it returns the relevant featured posts. Help, anyone?
I know this is an old one, but just in case someone stumbles upon it like I did today -- Woocommerce (I'm using v2.6.2) appears to store these custom attributes as taxonomies.
I suspect the correct args for the original question would look like this:
$args = array(
'post_type' => 'product',
'tax_query' => array(
array(
'taxonomy' => 'pa_on',
'field' => 'name',
'terms' => 'yes'
)
)
);
Using the appropriate values for my installation, it solved my problem.
For new woocommerce use:
$attribute = 'on';
$value = 'yes';
$args = array(
'post_type' => 'product',
'tax_query' => array(
array(
'taxonomy' => 'pa_' . $attribute,
'terms' => $value,
'field' => 'slug',
'operator' => 'IN'
)
)
);
If product attribute is saved as specific product attribute (i.e. not global), then you can't query it as taxonomy, instead you can use this snippet (copied from http://snippet.fm/snippets/query-woocommerce-products-product-specific-custom-attribute/):
// Set custom attribute name and value to search for
$attribute_name = 'color';
$attribute_value = 'green';
$serialized_value = serialize( 'name' ) . serialize( $attribute_name ) . serialize( 'value' ) . serialize( $attribute_value ); // extended version: $serialized_value = serialize( $attribute_name ) . 'a:6:{' . serialize( 'name' ) . serialize( $attribute_name ) . serialize( 'value' ) . serialize( $attribute_value ) . serialize( 'position' );
$args = array(
'post_type' => 'product',
'post_status' => 'any',
'posts_per_page' => -1,
'orderby' => 'title',
'order' => 'ASC',
'meta_query' => array(
array(
'key' => '_product_attributes',
'value' => $serialized_value,
'compare' => 'LIKE',
),
),
);
$loop = new WP_Query( $args );
while ( $loop->have_posts() ) {
$loop->the_post();
// do stuff here... e.g. get_the_ID()
}
wp_reset_postdata();
Guess what you need is a query with meta_query value set:
$args = array(
'post_type' => 'product',
'meta_query' => array(
array(
'key' => 'pa_on',
'value' => 'yes',
'compare' => '='
)
)
);
$query = new WP_Query( $args );
You can learn more about those here:
http://codex.wordpress.org/Class_Reference/WP_Query#Custom_Field_Parameters
I'm using WP_Query for Woocommerce products in attempt to query products in a particular category. This is the syntax that worked for me -
$args = array(
'posts_per_page' => -1,
'product_cat' => 'category-slug-here',
'post_type' => 'product',
'orderby' => 'title',
);
$the_query = new WP_Query( $args );
// The Loop
while ( $the_query->have_posts() ) {
$the_query->the_post();
echo '' . get_the_title() . '<br /><br />';
}
wp_reset_postdata();
This returns data, but I want to pass an ID, not a category slug, to filter and I want to find products that exist in multiple categories only.
The argument product_cat is not native to WP_Query (at least that I can find), so I'm assuming this is something custom to Woocommerce. Through their documentation, I haven't been able to find anything that will allow me to filter by category ID, nor use an AND condition for this filtering.
Using cat, the array of tax_query, and category__and have not yielded any results. Essentially, I would like to query all products that exist in both category ID 102, and 115. If I have to use slugs, I'm sure there is a way around getting that info based on the ID I have, but I'd like to avoid 2 queries to filter by multiple categories.
Does anyone know how to accomplish this?
UPDATE: I have learned that separating category slugs by commas in the product_cat argument will produce an "OR" effect, so it will combine distinct products from both, but this is not what I am looking for. So, for example:
'product_cat' => 'category-slug1, category-slug2'
will return products from both categories in total, but I am still searching for a way to find distinct products that ONLY belong to both, or multiple, categories.
Wow, so after hours of banging my head, this is how I was able to solve this -
$args = array(
'posts_per_page' => -1,
'tax_query' => array(
'relation' => 'AND',
array(
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => 'category-slug1'
),
array(
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => 'category-slug2'
)
),
'post_type' => 'product',
'orderby' => 'title',
);
$the_query = new WP_Query( $args );
This takes advantage of the tax_query argument, including the relation => 'AND' to make sure the product falls under BOTH categories.
Hope this helps someone in the future.
I was also not able to figure out how to pass an ID, rather than a slug (although I'm sure there's a way), but here's the function to retrieve the slug based on an ID:
$terms = get_term($YOURID, 'product_cat');
$theslug = $terms->slug;
From the WordPress codex on WP_Query for Category Parameters:
equivalent of OR
$args = array( 'product_cat' => 'category-slug1,category-slug2' );
equivalent of AND
$args = array( 'product_cat' => 'category-slug1+category-slug2' );
e.g.
$query = new WP_Query( $args );
To query by category_ID this is what worked for me.
// First obtain term id:
//...
$all_categories = get_categories( $args );
$cat_ids = array();
foreach ($all_categories as $cat)
{
array_push($cat_ids, $cat->term_id);
}
//Now use ids from array:
$args = array(
'posts_per_page' => -1,
'post_type' => 'product',
'tax_query' => array(
array(
'taxonomy' => 'product_cat',
'field' => 'id',
'terms' => $cat_ids
)
)
);
Inside a 'tax_query' array's array you can specify an 'operator' to be performed on the query. You can achieve what you want using the 'AND' operator.
$args = array(
'posts_per_page' => -1,
'tax_query' => array(
'relation' => 'AND',
array(
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => array( 'category-slug1', 'category-slug2' )
'operator => 'AND',
),
),
'post_type' => 'product',
'orderby' => 'title',
);
$the_query = new WP_Query( $args );
All of the products selected by this query will match the provided 'terms'. See this link for more info: https://codex.wordpress.org/Class_Reference/WP_Query#Taxonomy_Parameters
In case the link ever breaks, here's the relevant info:
operator (string) - Operator to test. Possible values are 'IN', 'NOT IN', 'AND', 'EXISTS' and 'NOT EXISTS'. Default value is 'IN'.