WooCommerce Save multiple attribute values on add to cart - php

I created a foodbowl-creator. http://klanten.visual.be/demoestuin/product/bowl-samenstellen/
I want to save my attributes with multiple values. In the step 'groenten' you can select multiple vegetables. But when I add it to the cart only saves one attribute for a variation. Wich is logical.
Can somebody tell me how to save multiple attribute values to the post object when I add this product to the cart?
Thank you in advance
EDIT :
I found a working example, but I have no way to contact that person. It is practically the same as I want to make : fingerfoodaffair-shop.ch/product/sandwich. In the screenshot you can see that there are multiple attributes in the string.
That's exactly what I want, how can you save multiple values from an attribute in a string like : attribute1, attribute2, attribute3

Using JQuery Get selected Attribute ID, Current Product id , Quantity ETC.
Then send ajax request . where your get ajax request paste this code. your all attribute add into cart . and in ajax responce windows redirect to cart page.
global $wpdb;
global $woocommerce;
$proid =$_POST['proid'];
$variationid =$_POST['valpj'];
$quantity =$_POST['quantity'];
$arr = array();
$arr['Photos'] = 'Pics';
foreach($variationid as $variationid1){
//echo $variationid1. '<br />';
$woocommerce->cart->add_to_cart( $proid, $quantity, $variationid1, $arr, null );
}

Related

Empty Array on first argument for woocommerce_add_cart_item_data filter hook

I am getting an empty array from the woocommerce_add_cart_item_data filter when a product is added to the shopping cart. Example added to functions.php of WordPress theme;
function TEST_post_filter($a,$b,$c) {
print_r($a); //THIS IS EMPTY ARRAY ie returns Array()
return $a;
}
add_filter('woocommerce_add_cart_item_data', 'Test_post_filter',10,3);
Any idea why this might be? I have found no reference to this issue anywhere. I have tried both basket behaviours ie Redirect to the basket page after successful addition and/ or Enable AJAX add to basket buttons on archives. I can't get my head around it. Plugins I have activated are WooCommerce, and WooCommerce Stripe Gateway.
UPDATE - Code which adds product options to product screen
function option_add_to_product() {
global $product;
//get pizza categories
$categories = get_terms( 'product_cat', array(
'hide_empty' => false,
));
$use_product = [];
for($i=0;$i<count($categories);$i++) {
if(strtolower($categories[$i]->slug) === 'bespoke_product')
array_push($use_product,$categories[$i]->term_id);
}
$include_product = false;
if(! count($use_product))
return false;
for($i=0;$i<count($use_product);$i++) {
$this_product_categories = $product->get_category_ids();
for($ii=0;$ii<count($this_product_categories);$ii++) {
if($this_product_categories[$ii] === $use_prouduct[$i]) {
$include_product = true;
break;
}
}
}
if(! $include_product)
return false;
//template to add product option
require plugin_dir_path(__FILE__) . 'templates/add_product_option.php';
}
You can see the html from add_product_option.php will be added to the product if the product has a a category with the slug "bespoke_product". Note, this method of getting a match for a product is temporary (just technical debt for now).
When the filter woocommerce_add_cart_item_data is called the data posted from the product form is available to the corresponding function. Unsanitised data might read as follows:
[extra_option_one] => 0
[extra_option_two] => 0
[extra_options_three] => 1
[extra_option_four] => 0
[order_note] =>
Each of those options will have a lookup table with a related price e.g. extra_options_three might be £1.50. This cost of this option and any others selected needs to up the price of the specific item being added to the cart. It should not be represented separately. The definition of the option added should go into the product field everywhere that purchased item is shown. I'm working through step by step, but it's not easy at the point I am at! I'm guessing the next is tha I'm going to be able to update the item in this order?
The woocommerce_add_cart_item_data hook is used to add custom data to the cart item on simple add to cart submission, like additional fields included in the <form> where "add to cart" button is located…
So if you are not submitting extra custom data from custom fields on add to cart event on (from single product pages), the first function argument is going to be an empty array…
See those related answer threads using this hook.

Wordpress Get value of hidden input field in functions.php

I have a hidden input field, which I want to fetch in my functions.php, but I keep getting NULL as a return value.
Here is my code:
add_filter('woocommerce_add_cart_item_data', 'add_custom_field_data_to_cart', 10, 2 );
function add_custom_field_data_to_cart($cart_item_data, $product_id, $variation_id) {
$cart_item_data['myHiddenInput'] = $_POST['myHiddenInput'];
return $cart_item_data;
}
Can someone maybe tell me why I get NULL ?
EDIT
The hidden input field is on my archive-products.php of my woocommerce-shop
<input type="hidden" name="myHiddenInput" value="">
The value gets set by using javascript
UPDATE
What I want to achive is, that I have an archive-products page where all my products are listed. Now, above my products I have a tab-menu with the next 5 days of the week. So I click the tab "Wednesday 19." the value of the hidden input gets the date of the active menu-tab:
<input type="hidden" name="chosenDate" value="2018-09-19">
Now I add a product to my cart. Then I click the menu-tab "Friday 21." - the value of the hidden filed gets updated -> I add a product to the cart.
Now when I go to my cart page - I want the products to have the dates listed when they will get delivered (the dates from the menu-tab when they were added)
as #LoicTheAztec Said
You can't pass anything custom from any archive page via ajax add to cart button as if you look to the source code of Ajax add to cart… There is no possible additional arguments or hooks. So you will need to build your own Ajax add to cart functionality, which is something huge and complicated. So your hooked function woocommerce_add_cart_item_data will have no effect
so the best logic is to use Javascript to achieve your goal and you can do it like the below solution:
First Lets add those value inside the add to cart button as an attribute instead of input tag.
for that we are going to us woocommerce_loop_add_to_cart_args hook as follow:
add_filter( 'woocommerce_loop_add_to_cart_args', 'change_item_price', 10, 2 );
function change_item_price( $args, $product ) {
$args['attributes'] = $args['attributes'] + [ 'data-chosen-date' => '2018-09-19' ];
return $args;
}
you can add as many attribute as you want and modify the value through your script and then store those value when the user click add to cart intro session storage and then in the cart page you can get those values and append them to cart table so for example:
add_action( 'wp_footer', 'script' );
function script() {
if ( is_shop() ) {?>
<script>
document.body.addEventListener('click', add_to_cart);
function add_to_cart(e) {
if (e.target.classList.contains('add_to_cart_button')) {
let val = e.target.getAttribute('data-chosen-date');
let product_id = e.target.getAttribute('data-product_id');
sessionStorage.setItem(product_id, val);
}
}
</script>
<?php
}
if ( is_cart() ) {
?>
<script>
var items = document.querySelectorAll("td");
items.forEach(function (item, index) {
if (item.classList.contains('product-remove')) {
var id = item.childNodes[1].getAttribute('data-product_id');
if (sessionStorage.getItem(id)) {
var textnode = document.createElement('p');
textnode.innerHTML = sessionStorage.getItem(id);
item.nextElementSibling.nextElementSibling.appendChild(textnode)
}
}
}); </script>
<?php
}
}
output :
The Date after the item link in the cart table has been retrieved from our storage session and each value we stored is maped with the product id as key in our storage session so we can have different value for each product.

Using wc_get_product() with a PHP variable for product ID

I'm building out custom landing pages for products in WooCommerce and I'd like to get the product price amongst other things in order to display them on the landing page.
Each landing page has some custom fields which allow the WP Admin to add in content, for the landing page as well as the product ID, which will then be used to generate the product price, checkout URL etc..
I can't get the wc_get_product(); to work with my custom field or a variable built off that. It only works when I use a straight ID. I think there's something I'm not understanding about how variables work within PHP. Here's my code.
<?php
//Gets the course ID from the custom field entered by user
$courseID = the_field('course_id');
// This line is where the problem is...
$_product = wc_get_product('$courseID');
// If I replace the line above with this line
// $_product = wc_get_product('7217');
// everything works great, but that does not let
// each landing page function based on the custom fields where the user determines
// the product ID they are selling on that landing page.
// Get's the price of the product
$course_price = $_product->get_regular_price();
// Output the Course price
?> <span class="coursePrice">$<?php echo $course_price;?></span>
Update
I get the following error using wc_get_product( $courseID ); or get_product( $courseID );:
Fatal error: Call to a member function get_regular_price() on a non-object in ...
Update related to your recent comment. The 2 ways to explore:
1) Instead of you should try to use to get the product object (avoiding the error):
$courseID = the_field('course_id');
// Optionally try this (uncommenting)
// $courseID = (int)$courseID;
// Get an instance of the product object
$_product = new WC_Product($courseID);
2) Alternatively if this doesn't work, you should try to use get_post_meta() function to get the product price (or any product meta data) this way:
<?php
//Gets the course ID from the custom field entered by user
$courseID = the_field('course_id');
// Get the product price (from this course ID):
$course_price = get_post_meta($courseID, '_regular_price', true);
// Output the Course price
?> <span class="coursePrice">$<?php echo $course_price;?></span>
This time you should get displayed the price with one or the other solutions.
Update: May be Also you need to convert $courseID to an integer variable.
Because you need to use your variable $courseID inside wc_get_product() (without the 2 ') function this way:
<?php
//Gets the course ID from the custom field entered by user
$courseID = the_field('course_id');
// Optionally try this (uncommenting)
// $courseID = (int)$courseID;
// Here
$_product = wc_get_product( $courseID );
$course_price = $_product->get_regular_price();
// Output the Course price
?> <span class="coursePrice">$<?php echo $course_price;?></span>
This should work now.
You can try this out :
$courseID = the_field('course_id');
$product = get_product( $courseID );
I figured out the answer after running through the possible solution routes that #LoicTheAztec supplied in his response. None of these worked and so I assumed something else was up.
I use Advanced Custom Fields to add custom fields in the back end and I was using ACF's the_field() in order to create my variable. That is incorrect usage of that function as it's designed to display the field, (it's basically using php's echo). To work with these custom field's you need to use ACf's get_field() which is to use it to store a value, echo a value and interact with a value.
Once I switched to setting my $courseID to this..
$courseID = get_field('course_id');
Everything worked. My code worked, and all #LoicTheAztec's code approaches also worked.

return woocommerce item names from cart only if they are a certain variation

I'm more or less a total newbie to php. My goal is to get the names of items from the logged in user's cart and dynamically populate a GravityForms template with the information. I've successfully managed to do that with the code below, but there are three things that I'm failing to do. 1: I only want to populate the form with all items of a certain variation. 2: the echo function will list all of the item names, but not inside the relevant field, and the return function will populate the field, but only with the first item name. 3: I'd like to have the output items listed with some form of separator in between each item name. Here's what I have so far:
<?php
add_filter( 'gform_field_value_beat_names', 'beat_names_function' );
function beat_names_function( $value ) {
global $woocommerce;
$items = $woocommerce->cart->get_cart();
foreach ($items as $item) {
$product_variation_id = $item['variation_id'];
$license_id = new WC_Product($product_variation_id);
$license_string = $license_id->get_formatted_name();
$beat_id = $item['data']->post;
$beat_name = $beat_id->post_title;
if (strpos($license_string, 'basic') !== false) {
echo $beat_name;
}
}
}?>
As you can see, I'm attempting to use strpos to isolate the particular item variation I want to target, using a certain word found in the name of the variation option, being "basic". I'm sure there's a more secure way of doing that, but it works for now. The problem lies with the return function I set up inside the conditional strpos statement, being that it will still just return the entire list of cart items, as opposed to only the items that I'm trying to isolate with the strpos conditional.
The ultimate goal is to create a license agreement that is dynamically populated with the relevant information, including the names of the items being licensed. The item variations are different license options that I have available for the products in my store. The purpose of the above code is to filter cart items by license type so that the wrong item names don't get listed on the wrong license agreement at checkout.
Any tips would be appreciated
Figured it out after some more tinkering. I broke it down step by step to help anyone as clueless as I am
add_filter( 'gform_field_value_basic_beat_names', 'basic_beat_names_function' );
function basic_beat_names_function( $value ) {
global $woocommerce;
$items = $woocommerce->cart->get_cart();
// the item names you want will be stored in this array
$license_check = array();
// Loop through cart items
foreach ($items as $item) {
// get the id number of each product variation in the cart. this won't work for "simple" products
$product_variation_id = $item['variation_id'];
// translate that id number into a string containing the name of the product, and the options applied to the product
$license_id = new WC_Product($product_variation_id);
$license_string = $license_id->get_formatted_name();
// check to see if the word "basic" is found anywhere in that string. "basic" is contained in the name of the product option being targeted
if (strpos($license_string, 'basic') !== false) {
// if the above condition is met, fetch the name of any products in the cart that have that option applied. The product name will be fetched from the title of the product's page
$beat_id = $item['data']->post;
$beat_name = $beat_id->post_title;
// store the retrieved product names in the $license_check array
$license_check [] = $beat_name;
}
}
// pull the stored product names from the $license_check array, and format them using implode and concatenation, then return the final result to the form field
return "\"" . implode("\", \"", $license_check) . "\"";
}
As a warning, the strpos method is a little hacky. It'll only work properly if your string is specific enough to target ONLY the option you're looking for.
As an example, here's the format for the product variation string being fed into the strpos function:
item-name-option-one-name-option-two-name – variation #xxx of item page title
So, if you want to filter items ONLY by option one, your safest bet would be to write the strpos function like so:
if (strpos($license_string, 'option-one-name') !== false) {
//do something
}
When all is said and done, the final result should look like: "item1", "item2", "item3", etc.
Then, to do the same with any other option, and output the result in a different field, or separate form altogether, I'll just duplicate this code, and replace any mention of the word "basic" with some different unique string contained in the other option. Don't forget to configure the gravity forms field as necessary too.

Get product id in magento

In magento,i want to add quick look feature like this http://www.timberlandonline.co.uk/on/demandware.store/Sites-TBLGB-Site/default/Link-Category?cgid=men_footwear_boots.I have added a hidden input & a div in list.phtml.If i click the div of any product javascript returns product id of first product in that category page.But it should return product id of the selected div.
You need to look into this page (<path_to_your_template_folder>/template/catalog/product/list.phtml) carefully. You will find the following lines of code in different places of this page only:-
$_productCollection = $this->getLoadedProductCollection();
foreach ($_productCollection as $_product):
$reqProductId = $_product->getId();
endforeach;
If you carefully match the above code & the code in the above-mentioned page, you will know that you need to use the variable "$reqProductId" properly in your required "INPUT" element of type "hidden". So you will require it to do your part in the main "foreach" loop.
Hope it helps.
Try below code to get currently loaded product id:
$product_id = $this->getProduct()->getId();
When you don’t have access to $this, you can use Magento registry:
$product_id = Mage::registry('current_product')->getId();
Also for product type i think
$product = Mage::getModel('catalog/product')->load($product_id);
$productType = $product->getTypeID();

Categories