Add product variations programmatically via specific data in WooCommerce - php

What i am trying to do is save a new variation but when saving it, it throws an error
Call to a member function get_name() on string;
The variations are being created but without any attribute value.
public static function create_product_variants($id,$product,$variant_data){
for($i=0; $i< count($variant_data); $i++){
$variant = new WC_Product_Variation();
$variant->set_parent_id($id);
foreach($variant_data[$i] as $key => $value){
if($key == 'attribute_name'){
$attribute_name = $value;
}
if($key == 'variant'){
if(gettype($value) == 'string'){
$variants = [$value];
}else{
$variants = $value;
}
}
}
if(count($variants) == count($attribute_name)){
$variant_attributes = array();
for($j=0; $j< count($variants); $j++){
$variant_attributes[$attribute_name[$j]] = $variants[$j];
}
$variant->set_attributes($variant_attributes);
}
$id = $variant->save();
}
}
The data passing through $variant_data is like:
[
{
attribute_name: ["Color","Size"]
price: "10"
quantity: "20"
variant: ["red","24"]
}
]
$id is product_id

There are some complications and mistakes in your code. Instead try the following revisited code:
public static function create_product_variants( $id, $product, $data ){
foreach( $data as $variation_data ){
if( isset($variation_data['attribute_name']) && isset($variation_data['variant']) ){
$variation = new WC_Product_Variation();
$variation->set_parent_id($id); // Set parent ID
$variation->set_regular_price($variation_data['price']); // Set price
$variation->set_price($variation_data['price']); // Set price
// Enable and set stock
if ( isset($variation_data['quantity']) ) {
$variation->set_manage_stock(true);
$variation->set_stock_quantity($variation_data['quantity']);
$variation->set_stock_status('instock');
}
$attributes = array(); // Initializing
$attribute_names = (array) $variation_data['attribute_name'];
$attribute_terms = (array) $variation_data['variant'];
// Formatting attributes data array
foreach( $attribute_names as $key => $attribute_name ){
$attributes[sanitize_title($attribute_name)] = $attribute_terms[$key];
}
$variation->set_attributes($attributes); // Set attributes
$variation_id = $variation->save(); // Save to database (return the variation Id)
}
}
}
It should better work.
The variations will be created/saved, the the method get_name() should not throw any error this time.

Do it simple like
public static function create_product_variants($id,$product,$variant_data){
foreach ($variant_data as $object){
$variant = new WC_Product_Variation();
$variant->set_parent_id($product->get_id());
$attributes = array_combine($object->attribute_name, $object->variant)
$variant->set_attributes($attributes);
$variant->save();
}
}
if the object is
[
{
attribute_name: ["Color","Size"]
price: "10"
quantity: "20"
variant: ["red","24"]
}
]

Related

Adding multiple values to same key in array php

I want to add multiple values into arrays, for same key.
I have this code:
public function getOnlySellers()
{
$sellers[] = array();
foreach ($this->getProducts() as $product) {
$product_id = $product['product_id'];
$getseller = $this->getSellerbyProduct($product_id);
$sellers[$getseller] = $product_id;
}
return $sellers;
}
Here I have for example: seller 1 with values: 100 and 101
Seller 2 with values: 107
But on my code, on seller 1 for example, is showing only last value 101, but not both.
What is wrong ?
And the call code:
$call = $this->cart->getOnlySellers();
foreach ($call as $seller => $products)
{
$show = "$show <br> $seller has value $products";
}
Thanks!
You could add an array of product ids to your $sellers array, allowing you to assign multiple product_ids to each seller. This [] operator will push the $product_id onto a new array at $sellers[$getseller].
$sellers[$getseller][] = $product_id;
The full code then being:
public function getOnlySellers()
{
$sellers[] = array();
foreach ($this->getProducts() as $product) {
$product_id = $product['product_id'];
$getseller = $this->getSellerbyProduct($product_id);
$sellers[$getseller][] = $product_id;
}
return $sellers;
}
When you output the values, you could use implode to glue the product ids together:
$call = $this->cart->getOnlySellers();
foreach ($call as $seller => $products)
{
$show = "$show <br> $seller has value ".implode(', ', $products);
}

PHP function for returning array with unique indexes

I have a simple problem. Lets say I have an array
Array
0
product_id 233
slug "zotac-geforce-gtx-1070-amp-extreme-edition-8gb-zt-p10700b-10p"
1
product_id 227
slug "zotac-geforce-gtx-1060-mini-6gb-gddr5-zt-p10600a-10l"
2
product_id 233
slug "zotac-geforce-gtx-1070-amp-extreme-edition-8gb-zt-p10700b-10p"
Now if you see there are two products having same product_id! I don't want that I am trying to get this array filtered from duplicate products
This is what I tried but it doesn't work
$temp_products = array();
foreach($products as $product)
{
if(count($temp_products) > 0)
{
foreach($temp_products as $temp_product)
{
if($temp_product['product_id'] != $product['product_id'])
{
$temp_products[] = $product;
}
}
}
else
{
$temp_products[] = $product;
}
}
It returns the same array as the original one. and $products is the main array having the data.
Try this! But I would definitely suggest using array_filter or array_unique will post an example later. Try this.
$temp_products = array();
$count = 0;
foreach($products as $product)
{
if(count($temp_products) > 0)
{
//foreach($temp_products as $temp_product)
//{
if($temp_products[$count]['product_id'] != $product['product_id'])
{
$temp_products[] = $product;
}
//}
}
else
{
$temp_products[] = $product;
}
}
Using array_unqiue
foreach($products as $product)
{
$temp_products[] = $product;
}
dd(array_unique($temp_products));
Another way would be to use a helper array to keep track of already present ids.
$temp_products = array();
$already_present = array();
foreach($products as $product)
{
$id = $product['product_id'];
if ( isset($already_present[ $id ] ) ) continue;
$temp_products[] = $product;
$already_present[ $id ] = '';
}
$products = $temp_products;

Add another dimension into array cart

I have a shopping cart, which works just fine, but I would like to store type of goods (for example color, size, etc.).
Here is a function that gets items from shopping cart
public static function getCart() {
if((isset($_SESSION['cart'])) && count($_SESSION['cart'])>0) {
$ids = "";
foreach($_SESSION['cart'] as $id => $quantity) {
$ids = $ids . $id . ",";
}
$ids = rtrim($ids, ',');
$dotaz = dibi::fetchAll("SELECT * FROM eshop_products WHERE idProduct IN ({$ids})");
return $dotaz;
} else {
//do nothing
}
}
And function that adds items to shopping cart
public static function addToCart($data) {
$id = $data['id'];
$quantity = $data['qty'];
$varianta = $data['varianty']; //THIS IS WHAT I NEED TO ADD TO SESSION ARRAY
if(!isset($_SESSION['cart'])) {
$_SESSION['cart'] = array();
}
if(isset($_SESSION['cart'][$id])) {
$_SESSION['cart'][$id] += $quantity;
} else {
$_SESSION['cart'][$id] = $quantity;
}
}
Is there some easy way to do that? I googled some tutorials, but still no success.
Thank you.
Maybe this is a hint for you:
$id = $data['id'];
$quantity = $data['qty'];
$varianta = $data['varianty']; //THIS IS WHAT I NEED TO ADD TO SESSION ARRAY
$cart = array();
array_push($cart, array(
'id' => $id,
'quantity' => $quantity,
'varianta' => $varianta
));

issues woocommerce add_to_cart with data

I have an issue when I'm trying to set a data into my item:
add_filter('woocommerce_add_cart_item_data', '_add_custom_item_data', 10, 2);
add_filter('woocommerce_get_cart_item_from_session', '_get_cart_item_from_session', 10, 2);
function _add_custom_item_data($cart_item_data, $product_id){
if(!empty($cart_item_data)){
$cart_item_data['custom_field'] = 'aaaa';
}
return $cart_item_data;
}
function _get_cart_item_from_session($cart_item, $values){
if (isset($values['custom_field'])) {
$cart_item['custom_field'] = $values['custom_field'];
}
return $cart_item;
}
when I use:
$woocommerce->cart->add_to_cart($id,'1','','',array('_my_data','000000000000000000000000000000'));
the _add_custom_item_data function is executed as well and I have the _my_data variable.
but i'm try to get the variable with my product:
$items = $woocommerce->cart->get_cart();
foreach($items as $item){
echo $woocommerce->cart->get_item_data( $item ) . "<br>";
}
I didn't see my variable...
Any idea?
At last function try following to get data
<?php
$cart = $woocommerce->cart->get_cart();
$items = 0;
$total = 0;
foreach ($cart as $p) {
$total += $p['line_total'];
$items += $p['quantity'];
}
echo $items;
echo $total;
?>
instead of assigning data directly to an index you should assign it to product_meta first, for example, you can try this
$item_meta['your_key] = 'your_value';
$cart_item_data ['product_meta'] = array('meta_data' => $item_meta);

Find the top level parent

I have a MySQL table with id, category_id (parent id), and url.
I have a class that looks something like this. I have removed all unnecessary functions.
class categoriesBuilder
{
var $items = array();
var $html = array();
function fetch_assoc_all( $sql )
{
$result = mysql_query( $sql, $this->conn );
if ( !$result ){
return false;
}
$assoc_all = array();
while( $fetch = mysql_fetch_assoc( $result ) ){
$assoc_all[] = $fetch;
}
mysql_free_result( $result );
return $assoc_all;
}
function get_categories()
{
$sql = 'SELECT id, category_id, url FROM categories ORDER BY category_id, id;';
return $this->fetch_assoc_all( $sql );
}
function get_category_string($root_id=0)
{
$this->html = array();
$this->items = $this->get_categories();
foreach ( $this->items as $item )
$children[$item['category_id']][] = $item;
// loop will be false if the root has no children
$loop = !empty( $children[$root_id] );
// initializing $parent as the root
$parent = $root_id;
$parent_stack = array();
while ( $loop && ( ( $option = each( $children[$parent] ) ) || ( $parent > $root_id ) ) )
{
if ( $option === false )
{
$parent = array_pop( $parent_stack );
}
elseif ( !empty( $children[$option['value']['id']] ) )
{
array_push( $parent_stack, $option['value']['category_id'] );
$parent = $option['value']['id'];
// HTML for menu item containing childrens (open)
$this->html[] = $option['value']['url'] . "/";
}
else
{
$this->html[] = $option['value']['url'] . "/";
}
}
return implode($this->html );
}
}
I need a function that returns only the top level parent. there may be several sub categories.
i.e.
category id 1
category id 3
category id 4
category id 5
category id 2
category id 6
In this example if i entered 3, 4 or 5 into the function the output would be 1. if i entered 6 i would get 2.
I also need a similar function that shows all parent folders.
for example if i entered 3 i would get 1 but if i entered 4 or 5 i would get 1-3
Thanks for your help.
Assuming your DB is like this:
(1, 0, URL1),
(3, 1, URL3),
(4, 3, URL4),
(5, 3, URL5),
(2, 0, URL2),
(6, 2, URL6)
Then you just need to walk up the list
e.g.
function get_top_parent($category_id, $root_id=0)
{
// Grab the id's and category's
$item_list = array();
foreach($this->items as $item) {
$item_list[$item['id']] = $item['category_id'];
}
$current_category = $category_id;
while(TRUE) {
if ($item_list[$current_category] == $root_id) {
// Check to see if we have found the parent category.
return $current_category;
} else {
// update our current category
$current_category = $item_list[$current_category];
}
}
}
function get_parents($category_id, $root_id=0)
{
$parents = array();
// Grab the id's and category's
$item_list = array();
foreach($this->items as $item) {
$item_list[$item['id']] = $item['category_id'];
}
$current_category = $category_id;
while(TRUE) {
// Check to see if we have found the root category.
if ($item_list[$current_category] == $root_id) {
return $parents;
} else {
// update our current category and parents
$current_category = $item_list[$current_category];
array_unshift($parents, $current_category);
}
}
}
reworked to return URL (I did not verify this code but it should work):
function get_top_parent($category_id, $root_id=0)
{
// Grab the id's and category's
$item_list = array();
foreach($this->items as $item) {
$item_list[$item['id']] = array(
'category_id' => $item['category_id'],
'url' => $item['url']
);
}
$current_category = $category_id;
while(TRUE) {
if ($item_list[$current_category]['category_id'] == $root_id) {
// Check to see if we have found the parent category.
return $item_list[$current_category]['url'];
} else {
// update our current category
$current_category = $item_list[$current_category]['category_id'];
}
}
}
function get_parents($category_id, $root_id=0)
{
$parents = array();
// Grab the id's and category's
$item_list = array();
foreach($this->items as $item) {
$item_list[$item['id']] = array(
'category_id' => $item['category_id'],
'url' => $item['url']
);
}
$current_category = $category_id;
while(TRUE) {
// Check to see if we have found the root category.
if ($item_list[$current_category]['category_id'] == $root_id) {
return $parents;
} else {
$temp_array = array(
'category_id' => $current_category
'url' => $item_list[$current_category]['url']
);
// update our current category and parents
$current_category = $item_list[$current_category]['category_id'];
array_unshift($parents, $temp_array);
}
}
}
The first function returns the URL, the second function should return an array of arrays... You will have the standard index, with "category_id" and "url" as nested/sub arrays... (If in doubt, just do a print_r of the return value to see what I mean)
again, i checkced the origional code but not the update...

Categories