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
Related
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.
There's an action called 'woocommerce_checkout_create_order_line_item' where you can use the method 'add_meta_data(meta_key, meta_value)' to add meta data to the order item.
Every example did use this syntax: add_meta_data(__('Some key name', 'woocommerce'), $value);
This is perfect as long as the admin and the customer have set the same language and the field is only informal.
But I have to process the field programmatically later. So the key must always be the same, no matter which language is used.
So I use a simple string, but it won't be translated in the admin order area, on the Thank-You page, in the shopping cart etc. anymore.
How can I override the automatic output of the order item meta data? I've tried to hook i.e. into 'woocommerce_before_order_itemmeta($item_id, $item, $product)' (Admin order page), but there I can only delete $item->delete_meta_data('my_key'), I cannot add temporary meta keys => $item->add_meta_data(__('Translated key'), $value);
I also tried:
$item->set_meta_data(array('id' => 0, 'key' => __('Translated key'), 'value' => 'test123'));
print_r($item->get_meta_data());
Thanks!
There is no need to do the translation in the meta key.
What you could do is use the hook woocommerce_order_item_display_meta_key. There you can catch your key and output a tranlation for display.
Also you can filter keys to not display all custom meta keys if you have some keys that should not show up in the order details, but are for internal use only. This can be done with woocommerce_hidden_order_itemmeta
Here is a good post on working with order item meta data: https://www.ibenic.com/manage-order-item-meta-woocommerce/
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 ).
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.
Does anyone have any idea how to add custom meta fields while making categories and fetch them in the loop in WordPress? I was wondering how to do that without hacking the WordPress core, but if I do – it won't become a hindrance to update WordPress in the future.
A plugin I have found that comes close is Wp-Category-Meta, but it doesn't have the ability to add checkboxes as fields in Edit Categories.
This will be very useful as users can make certain categories "featured", and then the code can use that meta value in the loop to style "featured" categories differently.
The problem:
Wordpress does not have a structure nor method to store "meta" values for taxonomies.
UPDATE 2017: WP 4.4+ has "term meta"!
For working with term metas use these:
update_term_meta()
get_term_meta()
delete_term_meta()
add_term_meta()
The Actions below are still valid though! :)
Additional reading: 4.4 Taxonomy Roundup
Solution for WP version <= 4.3.x and COMMON actions
Actions:
create_category and edit_category for category edit
category_add_form_fields and category_edit_form for category form fields
There are more actions than I've presented, but they seem to be deprecated (according to developer.wordpress.org).
The reason I chose the actions that I chose:
- They work on WordPress 4.4.2
- Due to lack of documentation I assumed these are the new ones replacing the deprecated ones...
Functions:
get_option( $option, $default );
update_option( $option, $new_value, $autoload );
update_option has two great abilities:
a) It craetes the option when such option does not exist yet
Unless you need to specify the optional arguments of add_option(),
update_option() is a useful catch-all for both adding and updating
options.
b) $new_value can be an integer, string, array, or object.
You may ask, why to use array/object? ...well, because each option = 1 database row => you probably want to store your category options in one row :)
The CODE
function my_category_form_fields($tag_object){
//output/display extra form fields, e.g. by echo ...
//ADD EXTRA SPECIFIC FIELD TO LATER CHECK IF IT'S CATEGORY SAVE/EDIT!
//(see note at 'edit_category' action...)
if( !empty($tag_object['term_id']) ){
//edit category form specific
//...load existing options with get_option( $option, $default );
} else {
//create category form specific
}
}
function my_category_save(){
//CHECK FOR YOUR EXTRA SPECIFIC FIELD TO CHECK IF IT'S CATEGORY SAVE/EDIT
//(see note at 'edit_category' action...)
//SECURITY CHECK
if( empty($_POST['EXTRA_SPECIFIC_FIELD']) || ! current_user_can('manage_categories') )
return null;
//save your form values using update_option()
//Recommendation:
//Add "category_" prefix and $category_id to your option name!
}
add_action( 'create_category', 'my_category_save', 10, 1 );
//Runs when a category is updated/edited,
//INCLUDING when a post or blogroll link is added/deleted or its categories are updated
//(which causes the count for the category to update)
add_action( 'edit_category', 'my_category_save', 10, 1 );
add_action( 'category_add_form_fields', 'my_category_form_fields', 10, 1 );
add_action( 'category_edit_form', 'my_category_form_fields', 10, 1 );
Create or Edit?
You might wonder whether you are creating or saving a category - this not documented yet (as far as I know), but from testing:
Edit save => $tag_object is object and contains some properties, most notably:
term_id
taxonomy
filter
Create save => $tag_object is just a regular string "category" - I guess this might change in the future...
General taxonomy
There are also actions like these for taxonomies in general - check these actions.
Jaz,
It looks like the plugin you mention in your original question has been updated to include a checkbox field (included in v1.2.3)
I think the Category SEO Meta Tags plugin will help you.
There is an updated and refactured version of this plugin to be found here:
https://wordpress.org/plugins/custom-taxonomy-category-and-term-fields/
Also added a WYSIWYG editor fieldtype.