In WooCommerce you can add attributes to a product in two ways.
method #1
a. Create an attribute in Product->Attributes, set a name for it (i.e color), define it wether to be a select-field or a text-field. Save.
b. Edit product switch to attributes-tab, select "color" from the dropdown, fill in some values. Save.
method #2
Edit product, switch to attributes-tab, select "add custom attribute", set a name, fill in some values. Save.
Well, in method #1, the attributes are saved and connected over three tables. wp_terms, wp_term_taxonomies and wp_term_relationship
In method #2, the attributes are serialized and saved in wp_postmeta with '_product_attributes' as meta_key.
my problem
What I would like to do now is to move all attributes that are stored in the wp_postmeta table, to the wp_meta table and connect them correctly via wp_term_taxonomies and wp_term_relationship.
Is there any solution or plugin for that?
Moving them manually is not an option since there are over 500 of them.
Cheers,
There is a WooCommerce-REST-API that allows me to do that.
http://woothemes.github.io/woocommerce-rest-api-docs/
First I had to get the slugs and names of all attributes (not their values) that are stored in the wp_term_relathionship. Since there are just a few, I wrote them down.
Get a JSON list of all products
Iterate through the attributes of the product
Compare it's name and slug to the one written down
If slug doesn't match, write the values to an attribute with the correct slug.
Example:
Product has two attributes called "Color". The one attribute is stored in wp_term_relationships and has name "Color" and slug "pa_attr_color". The other color is stored in wp_postmeta as pa_attributes, and has name "Color" and slug "wrong_color". Now I want to move that values to the pa_attr_color.
$product = [product =>
[
id => 123,
attributes => [
[name => 'Color', 'slug' => 'pa_attr_color', options => ['red', 'blue']],
[name => 'color', 'slug' => 'wrong_color', options => ['yellow', 'green']]
]]
All I have to do now is to move the options from wrong_color to pa_attr_color.
If there's no pa_attr_color, than I simply had to create one.
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.
I have 2 categories, called red and blue.
I have 2 posts, called red-post and blue-post. These posts are of their corresponding categories.
If I create the following query:
$bluePostQuery = new WP_Query(array('category' => 'red', 'name' => 'blue-post'));
This query will return blue-post, even though my query has category=red as a requirement. Why does this happen? blue-post is of the category blue, not red, so I want nothing returned here. Will a query always return if the name argument is provided, even if the other arguments are not met?
It may be ignoring 'category' because that is not a valid parameter for finding a category in WP Query. Here's a list of the valid params for cats. You might try using the category name parameter, like so:
$bluePostQuery = new WP_Query(
array(
'category_name' => 'red',
'name' => 'blue-post'
)
);
Alternatively, if you are searcing for a specific post, and know its slug, the category doesn't really matter, so you could just exclude it.
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/
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
I want to pass a parameter value to the route with the content of the current cell.
$listMapper->add("parent_id", 'url', array(
'route' => array(
'name'=>'admin_xxxxx_news_news_show',
'absolute'=>true,
'identifier_parameter_name'=>"parentID"
)
);
I have a route admin_xxxxx_news_news_show and have to pass the parameter from the current column. I don't have a relation of the current field with the related entity. I am using two columns for association, one for the entity and second for that entity ID. With my current knowledge of Symfony2 I need to have a customized view.