Wordpress custom field search - wordpress

I want to filter posts with respect to custom fields added to a post.Now I added two custom fields city,zip for each post. I want to filter posts with respect to these two fields.
How can write a custom query for it.
In the where clause I wrote meta_key='City' and meta_value='myval'. It works and returns the post with custom field City and value 'myval'. But I want to check both City and Zip.How can I do that.

I believe you use meta_query for this - just going through an old project now, looks like meta_query can take in an array of filters:
array( 'posts_per_page' => 10,
'meta_query' => array(
array('key'=>'key', 'value'=>'value', 'compare'=>'='),
array('key'=>'key2', 'value'=>'value2', 'compare'=>'=')
)
)
Obviously completely untested IRL, but looks like it works from my end.

Related

Query string in URL makes main query misbehave and pagination not to work in Wordpress

I have archive page of movies in which I am presenting all movies paginated. On side bar I have genres(taxonomy) for movies. When user clicks on one I want results on the page to be filtered according to which genre he clicked.
My way of thinking made me do this using query string in URL. So when user click on genre it requests same URL (archive for movies) but adds ?genre=SOMETHING. Then in pre_get_posts hook I have this if statement to modify main query:
if(
!is_admin() &&
$query->is_main_query() &&
is_post_type_archive('movie') &&
get_query_var('genre')
)
Then after that I have code like this to filter movies by genre user clicked on :
$taxonomyQuery = [
[
'taxonomy' => 'genre',
'field' => 'slug',
'terms' => get_query_var('genre'),
],
];
$query->set('tax_query', $taxonomyQuery);
Sidebar link are constructed like this :
<a href="<?php echo esc_url(add_query_arg('genre', $genre->slug)) ?>">
<?php echo $genre->name; ?>
</a>
Taxonomy is created with name genre so that name is automatically added to query_vars.
When I open archive page of movies /movies/ I get paginated results and everything works fine. But once I click on genre I get this path /movies/?genre=comedy.
pre_get_posts activates and filters movies according to the genre selected but pagination doesnt work. Even if I set $query->set('posts_per_page', 1); I still get more than one result returned from query. Problem only occurs when query string ?genre=SOMETHING gets added to URL and I cannot figure out why.
NOTE: I am relatively new to wordpress development and I do not actually know if this is the right way to do this kind of thing.
Any help is appreciated!
So after some testing with different things I got to this conclusion.
When I registered taxonomy with register_taxonomy I did not place 'query_var' property as I thought it is adding query string value like when you use :
add_filter('query_vars', 'demo_query_vars');
function demo_query_vars($queryVars) {
$queryVars[] = 'genre';
return $queryVars;
}
These two thing are not the same. First one enables you to load taxonomy using query_var. From the docs :
Sets the query var key for this taxonomy. Default `$taxonomy` key. If false, a taxonomy cannot be loaded at `?{query_var}={term_slug}`. If a string, the query `?{query_var}={term_slug}` will be valid.
Second one enables custom query_var and query string to be used, which is what i needed.
FIX: Just disable query_bar 'query_var' => false'
Then add code I posted above to allow query variable to be processed (add_filter function) and you will be able to use your query_var.
NOTE: This problem was caused for me because I my taxonomy is called genre therfore query_var in register_taxonomy function is automatically set to this value. And I also wanted to use the same name for my own custom query_var which made conflicts.
If your taxonomy name is different from your query_var (the query string you wich to use, example if I used ?g=SOMETHING instead of ?genre=SOMETHING) YOU WILL NOT run into this problem since there will be no conflicts between these two variables..
Another possible solution would be to make your custom query_var different than one specified in register_taxonomy if you are using query_var defined in register_taxonomy function. They just need to be different so there are no conflicts.
I am just at the beginning so this potentially could not be right but it for sure has something to do with these 2 variable names being the same.

Use another product as option - WooCommerce

Before I get too far down this rabbit hole...
I have a product in a category that is essentially a selection of 4 other products. It can be any combination of select products. Pricing is based off of regular price for those products.
What I've managed so far
Controlled through normal WooCommerce attributes interface. Admin puts in an attribute use-for-custom with the value being the category of item, i.e. cupcakes
The result is an association to a product slugged custom-assortment in the cupcakes category. This product will be an option for any/all of the 4 selections in the custom-assortment product in cupcakes category.
I also have a function in functions.php that queries all products with this set attribute and builds a neat little array of id/title/cost. I managed that via this post earlier, plus
$useable = array();
foreach ($products as $product){
$useable[] = array(
'id' => $product->ID,
'name' => $product->post_title,
'desc' => $product->post_excerpt,
'cost' => floatval(wc_get_product($product->ID)->get_price())/4
//cost is 1/4 as 4 will be selected to create 1 new product
);
}
Notes
It does not need to actually relate the selection back to a particular product. Having the selected product name(s) shown in the final order is enough for the admin. However, it would be nice to keep that reference as it may lead to additional functionality later.
Not concerned with stock at the moment, or any other attributes from the selected products except price.
Thoughts
I've tried a little to get custom variations to create programmatically via this post from LoicTheAztec, but so far I haven't gotten them to show up. I might be able to with a little more poking as his stuff is usually spot-on.
foreach ($useable as $useit){
$display = $useit['name'] . " (" . $useit['cost'] . ")";
$variation_data = array(
'attributes' => array(
'flavor-one' => $display,
'flavor-two' => $display,
'flavor-three' => $display,
'flavor-four' => $display
),
'sku' => '',
'regular_price' => $useit['cost'],
'sale_price' => ''
);
var_dump($product->get_id());
create_product_variation($product->get_id(), $variation_data);
}
Alternatively, I could probably create the drop-down selections manually and run a filter on the price based on selections. That seems like a lot of manual recreation of functionality though - checking validity, pricing, etc.
Final question
Is there a way to use one product as a variable product attribute for another product already? It doesn't seem like something far-fetched, but I haven't been able to google-foo anything. My google-foo has not been great recently.
Assuming a single product that can be any combination of 4 of 10 other products, using variations means 10,000 possible products added. That seems unreasonable, so I went with the option of doing this another way.
Will expand this answer with code shortly, but basically:
Query posts to get product type posts with the custom attribute grouping it with this configurable option. Output these as select elements with options of items in the add-to-cart form. Option values as product IDs and displayed as product name + price for that option.
Hook to the add to cart action to check options (passed in the $_POST) and store them as attributes on the cart item.
Hook to the cart pricing filter and use the cart item attributes to calculate final product price based on the assortment products' original prices.
Also:
add attribute display to the cart
add front-end control to display changing price with the changing attributes

Sort and paginate by custom date field with Wordpress / ACF / Timber

I'll try to describe what it is I want to achieve, please let me know if too much/not enough detail!
I'm making a site that needs to have documents uploaded to it. These documents will belong to one only of four categories and there will be one page per category. On this page, by default all documents will display. Users will also be able to view only the documents from each year by clicking a link.
It also needs to have pagination so a max of 10 documents are displayed per page.
So how I would ideally like to do this is to make a custom post type (documents) which would then display an ACF custom field set. The field set would have three fields (doc_type, doc_file and release_date). doc_type would be a select field of the four categories, doc_file a file upload and release_date a datepicker field.
When you click on a page, the controller would select by doc_type to only show the documents that belong to that category.
I want to order by release_date and use the year from this field as the display text of my links. For the actual href, I'm imagining something like /path/to/page.php?year=2017.
So there's a few problems here: first is that I am not sure if what I want to do is even possible - let alone a good way of doing things - with WordPress. I'm more used to pure PHP and mySQL, and so I might be trying to shoehorn more general solutions into WP. Can anyone confirm if it's possible to achieve what I want?
Second, I'm specifically running into some issues when I try to execute this plan.
I can successfully get each page to only display the documents that belong to it, like so (although I'm generating $last by grabbing info from the URI, which seems dodgy).
$docArgs = array(
'post_type' => 'documents',
'meta_key' => 'doc_type',
'meta_value' => $last,
);
$context['documents'] = Timber::get_posts($docArgs);
When I try to get my sorting on though, de nada:
$docArgs = array(
'post_type' => 'documents',
'meta_key' => 'doc_type',
'meta_value' => $last,
'meta_query' => array(
array(
'key' => 'release_date',
'orderby' => 'meta_value_num',
'order' => DESC,
),
),
);
I assume I've got the syntax wrong, but I'm basically really confused about the whole thing. Any suggestions?

ACF fields value not available until saving post manually

I have some custom post type "video" and I added some custom ACF fields to it ("video_path", "author_name" and "audio_author"). I'm generating posts in that type programmatically like this:
$video_post_params = array(
'post_title' => wp_strip_all_tags($video_title),
'post_status' => 'publish',
'post_author' => 1,
'post_type' => 'video'
);
$video_id = wp_insert_post( $video_post_params );
update_field('video_path', $video_path, $video_id);
update_field('author_name', $video_author, $video_id);
update_field('audio_author', $audio_author, $video_id);
All values are inserted well - when I open the post in back-end everything is fine. However, when I try to use those values, I don't get anything?!?
I'm reading values from template files like this:
get_field('video_path', $video_id)
And if I open the post and just save it without any change everything starts working normally and I'm getting post ACF fields normally after that. Posts created manually, from back-end are working well all the time.
What I'm doing wrong? Do I need some extra step when generating posts from code?
The issue is reported here:
http://support.advancedcustomfields.com/forums/topic/programmatic-post-insertion-acf-fields-and-the-save_post-hook/
But that solution is obviously not working for me - my update_field() functions already are immediately after wp_insert_post().
Found it!
When inserting ACF field value field key must be used. If key name is used instead, as I did, everything is inserted well at first look, but value isn't available until post is saved manually. So it's like:
update_field('field_56e683ab6265f', $video_path, $video_id);
update_field('field_56e68415b5c4b', $video_author, $video_id);
update_field('field_56e6842d58740', $audio_author, $video_id);
What a mess....
If you want to use the field name instead of the field key, you can use add_post_meta
For example:
add_post_meta($video_id, 'video_path', $video_path, true);
add_post_meta($video_id, 'author_name', $video_author, true);
add_post_meta($video_id, 'audio_author', $audio_author, true);
With ACF5 you have to use not post id, but post object, lake that:
update_field('field_56e683ab6265f', $video_path, $video);
update_field('field_56e68415b5c4b', $video_author, $video);
update_field('field_56e6842d58740', $audio_author, $video);
I had the same problem, and I correct it with simply add do_action('acf/save_post', $postID); at the end of the script, and that's all…

How to alphabetically sort custom posts if taxonomy is equals to 'custom_taxonomy'?

I'm trying to sort my custom posts alphabetically without touching any of the core files of the plugin.
I've tried the code below in functions.php and it works. BUT I want it to apply only to a certain custom taxonomy and/or post type.
function set_custom_post_types_order($wp_query) {
// 'orderby' value can be any column name
$wp_query->set('orderby', 'title');
// 'order' value can be ASC or DESC
$wp_query->set('order', 'ASC');
}
add_filter('pre_get_posts', 'set_custom_post_types_order');
I've also tried adding filter through it using "get_post_type" but it doesn't sort posts anymore.
note: it goes through the filter and display test var_dump in each post.
you can add conditions to check if its a taxonomy ( http://codex.wordpress.org/Conditional_Tags#A_Taxonomy_Page_.28and_related.29 ) and/or a specific post type ( http://codex.wordpress.org/Function_Reference/get_post_type, use your query object to get the correct ID ).

Resources