I have a form to submit new books to my WooCommerce website. I used to have it just save the book’s condition as a Product Attribute.
// Set the book's condition
$condition = $_POST['condition'];
wp_set_object_terms( $product_id, $condition, 'pa_condition', true );
$att_condition = Array('pa_condition' =>Array(
'name'=>'pa_condition',
'value'=>$condition,
'is_visible' => '1',
'is_taxonomy' => '1'
));
update_post_meta( $product_id, '_product_attributes', $att_condition);
That was easy. Now I am trying to add the Book Author’s name and the Genre, but when I duplicated the code it only sets the last Product Attribute. I know I should probably put it in a loop, but I’m being stupid and otherwise I can’t figure out what I am missing.
$condition = $_POST['condition'];
$genre = $_POST['genre'];
$author = $_POST['author'];
wp_set_object_terms( $product_id, $condition, 'pa_condition', true );
$att_condition = Array('pa_condition' =>Array(
'name'=>'pa_condition',
'value'=>$condition,
'is_visible' => '1',
'is_taxonomy' => '1'
));
update_post_meta( $product_id, '_product_attributes', $att_condition);
wp_set_object_terms( $product_id, $genre, 'pa_genre', true );
$att_condition = Array('pa_genre' =>Array(
'name'=>'pa_genre',
'value'=>$genre,
'is_visible' => '1',
'is_taxonomy' => '1'
));
update_post_meta( $product_id, '_product_attributes', $att_genre);
wp_set_object_terms( $product_id, $author, 'pa_author', true );
$att_author = Array('pa_author' =>Array(
'name'=>'pa_author',
'value'=>$author,
'is_visible' => '1',
'is_taxonomy' => '1'
));
update_post_meta( $product_id, '_product_attributes', $att_author);
3
Answers
I found the solution on https://stackoverflow.com/a/45475863/12092133.
I took my form variables and threw them into an array, and then ran this foreach and it did the trick.
you can try using
add_post_meta
function insteadupdate_post_meta
in this caseIt’s good that you’ve found a solution. However, the question of the original problem has gone unanswered, and there is a simple fault in your solution which should be improved upon.
To the original question.
There are multiple issues in your original code.
Your variable naming and usage in your code contains an error. The second call to update_post_meta; you assign $att_condition variable but use att-genre. If you want to use 3 variables, correct this. However, the code still won’t work.
You call update_post_meta for the same meta_key _product_attributes 3 times with (assuming the correction to the first issue) 3 different variables ($att_condition, $att_genre, $att_author). update_post_meta overwrites the value of the meta_key, if found and different to the value being passed. Though you’ve assigned array values to the variables, they are each distinct and hold only one array record. And so the last call to update_post_meta overwrites the previous writes.
Rather, you want to be assigning all your attribute array data to a single array variable and then making a single call to update_post_meta. Which will then update correctly with all the attributes you have added.
Which then leads towards the more robust and supportable foreach style solution you have come to.
The simple issue you have in your solution is one of performance. You have included
within the foreach loop instead of outside it. So, this will currently still write to the database via update_post_meta 3 times, with incrementally larger payloads as you iterate your input array and build up $thedata.
Solution:
Move the update_post_meta call to after your foreach so that only one call is made per execution.
Finally, wrap this call and likely also either your initial assignment to your $my_product_attributes or the usage of $value in any relevant conditional logic you determine appropriate for your needs regarding initialisation and handling of empty values.