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;
I have a data array that totals all the items in the cart for all the products as one number.
I've been trying to figure out a way to get a data array count() all the different totals of all the different items in the cart and have them presented in my data layer comma separated. I hope that makes sense.
if ($order->getId()) {
$items = $order->getAllVisibleItems();
$itemIds = array();
$itemNames = array();
$itemPrices = array();
$itemMargins = array();
$itemTypes = array();
$itemGenders = array();
$itemSports = array();
$itemCategoryIds = array();
$itemCategoryNames = array();
/** #var Mage_Sales_Model_Quote_Item $item */
foreach ($items as $item) {
// Get the parent item - it is NOT included in the quote due to
// customizations made by the OrganicInternet module for simple
// product pricing. So I had to come up with another way to get it.
$options = $item->getProductOptions();
$parent = $item->getProduct();
if (array_key_exists('info_buyRequest', $options)) {
if (array_key_exists('cpid', $options['info_buyRequest'])) {
$parentId = $options['info_buyRequest']['cpid'];
$parent = Mage::getModel('catalog/product')->getCollection()
->addAttributeToSelect('name')
->addAttributeToSelect('season')
->addAttributeToSelect('gender')
->addAttributeToSelect('sport')
->addAttributeToFilter('entity_id', $parentId)
->getFirstItem();
}
}
$itemIds[] = $item->getSku();
$itemNames[] = $parent->getName();
$itemPrices[] = $item->getBasePrice() ?: 0;
$itemMargins[] = $this->_calculateMargin($parent, null, $item);
$itemTypes[] = $parent->getAttributeText('season');
$itemGenders[] = $parent->getAttributeText('gender');
$itemSports[] = $parent->getAttributeText('sport') ?: 'Other';
$categories = $this->_getAllCategoryIdsAndNames($item->getProduct());
$itemCategoryIds[] = $categories['id'];
$itemCategoryNames[] = $categories['name'];
}
// # Products
$data['u1'] = count($items);
The above will return:
dataLayer = [{"visitorLoginState":"Logged out","visitorType":"NOT LOGGED IN","visitorLifetimeValue":0,"visitorExistingCustomer":"No","u1":2,"u2":["889623392590","889623135517"]
It shows a total of 2 products for the U1 variable and the two sku's for the u2 variable in the data array.
If i have multiple products for the first sku i want it to seperate the quantities. ie.. "u1":1,1,3
Would i use array_sumor some type of multi-dimensional array to acquire my needs?
If i have multiple products for the first sku i want it to seperate
the quantities. ie.. "u1":1,1,3
It is not exactly clear to me is the relationship between sku and product and which variables in your array refer to which. I make the following presumptions:
1) A product is equivalent to one $items element
2) A sku is a unique $itemIds[] value
I use the array key as a simple way to keep track for each unique sku and the value to keep track of the product count for the sku.
if ($order->getId()) {
$items = $order->getAllVisibleItems();
$itemIds = array();
$itemNames = array();
$itemPrices = array();
$itemMargins = array();
$itemTypes = array();
$itemGenders = array();
$itemSports = array();
$itemCategoryIds = array();
$itemCategoryNames = array();
// My addition (UPDATE: fixed to the correct variable name)
$uniqueItemIds = array();
/** #var Mage_Sales_Model_Quote_Item $item */
foreach ($items as $item) {
// Get the parent item - it is NOT included in the quote due to
// customizations made by the OrganicInternet module for simple
// product pricing. So I had to come up with another way to get it.
$options = $item->getProductOptions();
$parent = $item->getProduct();
if (array_key_exists('info_buyRequest', $options)) {
if (array_key_exists('cpid', $options['info_buyRequest'])) {
$parentId = $options['info_buyRequest']['cpid'];
$parent = Mage::getModel('catalog/product')->getCollection()
->addAttributeToSelect('name')
->addAttributeToSelect('season')
->addAttributeToSelect('gender')
->addAttributeToSelect('sport')
->addAttributeToFilter('entity_id', $parentId)
->getFirstItem();
}
}
// *******************************
// My addition / changes
$sku = $item->getSku();
$itemIds[] = $sku; // I don't use this but keep $itemIds for compatibility
// use the array key to track counts for each sku
if (!isset($uniqueItemIds[$sku])){
$uniqueItemIds[$sku] = 1; // UPDATE: fixed to start at 1 not 0
} else {
$uniqueItemIds[$sku]++;
}
// *******************************
$itemNames[] = $parent->getName();
$itemPrices[] = $item->getBasePrice() ?: 0;
$itemMargins[] = $this->_calculateMargin($parent, null, $item);
$itemTypes[] = $parent->getAttributeText('season');
$itemGenders[] = $parent->getAttributeText('gender');
$itemSports[] = $parent->getAttributeText('sport') ?: 'Other';
$categories = $this->_getAllCategoryIdsAndNames($item->getProduct());
$itemCategoryIds[] = $categories['id'];
$itemCategoryNames[] = $categories['name'];
}
// show # Products
// "u1":1,1,3 NOTE: this should be a string => "u1":"1,1,3"
$data['u1'] = "";
foreach ($uniqueItemIds as $key => $val)
// show unique skus in u2
$data['u2'][] = $key;
// show counts for each sku in u1
if (strlen($data['u1'] == 0)){
$data['u1'] = (string)$value;
} else {
$data['u1'] .= ("," . $value);
}
}
How about something like...
if ($order->getId()) {
.....
.....
.....
/** #var Mage_Sales_Model_Quote_Item $item */
$sku_based_array = array();
foreach ($items as $item) {
......
......
......
$categories = $this->_getAllCategoryIdsAndNames($item->getProduct());
$itemCategoryIds[] = $categories['id'];
$itemCategoryNames[] = $categories['name'];
if (isset($sku_based_array[$item->getSku()])) {
$sku_based_array[$item->getSku()] = $sku_based_array[$item->getSku()]++;
} else {
$sku_based_array[$item->getSku()] = 1;
}
}
// # Products
$data['u1'] = array_values($sku_based_array);
Looking at the code it looks like it will only every return one product as the $parent variable is overwritten to get a first item. I have added a new variable named $itemProductCounts this will be returned to the output $data array as itemProductCounts I suspect this will always equal one.
<?php
if ($order->getId()) {
$items = $order->getAllVisibleItems();
$itemIds = array();
$itemNames = array();
$itemPrices = array();
$itemMargins = array();
$itemTypes = array();
$itemGenders = array();
$itemSports = array();
$itemCategoryIds = array();
$itemCategoryNames = array();
$itemProductCounts = array();
/** #var Mage_Sales_Model_Quote_Item $item */
foreach ($items as $item) {
// Get the parent item - it is NOT included in the quote due to
// customizations made by the OrganicInternet module for simple
// product pricing. So I had to come up with another way to get it.
$options = $item->getProductOptions();
$parent = $item->getProduct();
if (array_key_exists('info_buyRequest', $options)) {
if (array_key_exists('cpid', $options['info_buyRequest'])) {
$parentId = $options['info_buyRequest']['cpid'];
$parent = Mage::getModel('catalog/product')->getCollection()
->addAttributeToSelect('name')
->addAttributeToSelect('season')
->addAttributeToSelect('gender')
->addAttributeToSelect('sport')
->addAttributeToFilter('entity_id', $parentId)
->getFirstItem();
}
}
$itemIds[] = $item->getSku();
$itemNames[] = $parent->getName();
$itemPrices[] = $item->getBasePrice() ?: 0;
$itemMargins[] = $this->_calculateMargin($parent, null, $item);
$itemTypes[] = $parent->getAttributeText('season');
$itemGenders[] = $parent->getAttributeText('gender');
$itemSports[] = $parent->getAttributeText('sport') ?: 'Other';
$categories = $this->_getAllCategoryIdsAndNames($item->getProduct());
$itemCategoryIds[] = $categories['id'];
$itemCategoryNames[] = $categories['name'];
$itemProductCounts[$item->getSku()] = count($parent);
}
// # Products
$data['u1'] = count($items);
$data['itemProductCounts'] = $itemProductCounts;
With that all being said, the code above should get you close to what you need, you should replace the line $itemProductCounts[$item->getSku()] = count($parent); with the correct array with the product counts for that SKU.
Part of the issue with your data here is that everything in an $item is hidden behind an accessor. Rather than creating multitudes of arrays, I would suggest either creating a new object to house the information, or just modifying the $item directly.
Messing with the object directly has the risk of you accidentally using a variable name that exists in a protected or private scope though, so probably best to use your own, like so.
if ($order->getId()) {
$items = $order->getAllVisibleItems();
// only need one array, no need for all data points to have their own
$myItems = [];
/** #var Mage_Sales_Model_Quote_Item $item */
foreach ($items as $item) {
// basic shell
$myItem = [];
// get $options and $parent
// ...
// build your own data object
$myItem['sku'] = $item->getSku();
$myItem['name'] = $parent->getName();
$myItem['price'] = $item->getBasePrice() ?: 0;
$myItem['margin'] = $this->_calculateMargin($parent, null, $item);
$myItem['type'] = $parent->getAttributeText('season');
$myItem['gender'] = $parent->getAttributeText('gender');
$myItem['sport'] = $parent->getAttributeText('sport') ?: 'Other';
$categories = $this->_getAllCategoryIdsAndNames($item->getProduct());
$myItem['categoryId'] = $categories['id'];
$myItem['categoryName'] = $categories['name'];
$myItems[] = $myItem;
}
// At this point, $myItems is manipulable by all the array_* functions
// number of items e.g. 3
$data['u1'] = count($myItems);
// array of skus e.g. ["889623392590","889623392590","889623135517"]
// note: can use objects for $myItem if on PHP 7
// if you like -> notation better (in the loop)
$skus = array_column($myItems, 'sku');
// array of skus with counts e.g. ["889623392590" => 2, "889623135517" => 1]
$skus_with_counts = array_count_values($skus);
// just the counts (assuming indexes on other arrays must match) e.g. [2, 1]
// note: might be useful if you want to keep the counts as an array in dataLayer
$sku_counts = array_values($skus_with_counts);
// if you want this as a comma-separated list for u1, e.g. "2,1"
// note: will also work if you implode $skus_with_counts
$data['u1'] = implode(',', $sku_counts);
// get a list of unique SKUs (both will work), e.g. ["889623392590","889623135517"]
$data['u2'] = array_unique($skus);
$data['u2'] = array_keys($skus_with_counts);
}
Most of these kinds of PHP functions will work on your other data types as well if you want to do counting and clustering, and as you point out, you can run sum operations over them as well if you wish.
PHP array manipulation references: array_column, array_count_values, array_values, implode, array_unique, array_keys.
As a sidebar, Mage_Sales_Model_Quote_Item does have a getParentItemId() method available and a getQtyOptions method, which returns both the quantity and the product model.
I think you are mixing things.
In a simple sistem you should have:
Order has an array of OrderedItems
Each OrderedItem stores ProductObject and OrderedQuantity
And the ProductObject contains all product data.
So in your example instead of counting SKUs you must have $item->quantity field and you should work with that when you add/delete/edit order contents.
I am working on opencart.I dont want to allow users to add same product multiple times in cart. for this i have a logic that i want to compare the products in cart. I will get the the product id of each product(how many the user added by clicking add to cart) than i will compare those ids. If they are same i will show them error message else they can carry on. For this logic i have used this code till now.
$products = $this->cart->getProducts();
foreach ($products as $product)
{
$p_id=$product['product_id'];
}
But i dont get that how will i compare 2 product ids in foreach loop. and than add my logic that if product ids are equal show error message.
You can simply check it at the time when user add a product to cart. To do so modify add function in controller->checkout->cart.php
In public function add() {
Add
$products = $this->cart->getProducts();
if($products){
foreach ($products as $product)
{
if($this->request->post['product_id'] == $product['product_id']){
$json['error']['blabla'] = 'Your warning message.';
break;
}
}
}
Before
if (!$json) {
And display that error wherever you want to display. That's it.
you can get the value of new product id and than compare it like this
//get product id to be added
$new_product = "get ID";
$products = $this->cart->getProducts();
foreach ($products as $product)
{
$p_id=$product['product_id'];
//compare with new product_id with existing
if ($_pid == $new_product){
echo " Product already exists!!";
}
}
$products = $this->cart->getProducts();
$exist = false;
foreach ($products as $product)
{
if ($p_id == $product['product_id']) {
$exist = true;
break;
}
}
if (!$exist) {
//add product co cart
}
Try this way
$products = $this->cart->getProducts();
$p_id = '';
foreach ($products as $product)
{
if($p_id != $product['product_id']) {
$p_id=$product['product_id'];
}else{
echo " Product already exists!!";
}
}
This will get you both a unique list of ID's and a list of ID's that needed to be removed to make the list unique.
// get the list of ID's
$products = $this->cart->getProducts();
$all = array();
foreach ($products as $product)
{
$all[] = $product['product_id'];
}
// Flip the array twice to just get the unique ID's
$unique = array_flip(array_flip($all));
// Get a list of ID's that were lost
$difference = array_diff_assoc($all, $unique);
I am getting an error:
Fatal error: Call to a member function getProducts() on a non-object
in
/var/www/vhosts/designsense.net.au/gypsy/public_html/catalog/controller/module/cart.php
on line 23
This is the code i am using.
class ControllerModuleCart extends Controller {
protected function index() {
$this->language->load('module/cart');
$this->data['heading_title'] = $this->language->get('heading_title');
$this->data['text_subtotal'] = $this->language->get('text_subtotal');
$this->data['text_empty'] = $this->language->get('text_empty');
$this->data['text_remove'] = $this->language->get('text_remove');
$this->data['text_confirm'] = $this->language->get('text_confirm');
$this->data['text_cart'] = $this->language->get('text_cart');
$this->data['text_checkout'] = $this->language->get('text_checkout');
$this->data['button_checkout'] = $this->language->get('button_checkout');
$this->data['button_remove'] = $this->language->get('button_remove');
$this->data['text_cart'] = $this->language->get('text_cart');
$this->data['cart'] = $this->url->link('checkout/cart');
$this->data['checkout'] = $this->url->link('checkout/checkout', '', 'SSL');
// Get Cart Products
$this->data['products'] = array();
foreach ($this->cart->getProducts() as $result) {
$option_data = array();
foreach ($result['option'] as $option) {
$option_data[] = array(
'name' => $option['name'],
'value' => (strlen($option['option_value']) > 20 ? substr($option['option_value'], 0, 20) . '..' : $option['option_value'])
);
}
Any suggestions on what could be causing this?
Try to load the model before you call the function getProducts()
$this->load->model('catalog/product');
You cant use $this->cart->getProducts(); in foreach loop.
So that you need to assign value to variable
$products = $this->cart->getProducts();
This little line of code is most important in that it makes a call to the function getProducts which is a core procedure located in system/library/cart.php. The variable $products now has the entire cart array + all possible options and can be “iterated” through. To iterate means to sift through an array, gathering it’s contents or to LOOP through. Let’s take a look at what is happening in the function getProducts(); In system/library/cart.php find this function towards the top:
then use this in foreach loop
foreach ($products as $product)
{
//your code here
}
This code is the foreach() loop set up to go through the array we just set up in system/library/cart.php. It is responsible for displaying all of the content seen in the shopping cart page along with the product options. Everything below foreach ($products as $product) { will repeat itself as many times as necessary until ALL PRODUCTS HAVE BEEN DEALT WITH IN THE ARRAY.
This will work fine.
Read this Article as well
EDIT 01
public function getProducts()
{
if ( !$this->data )
{
foreach ( $this->session->data['cart'] as $key => $quantity )
{
$product = explode(':', $key);
$product_id = $product[0];
$stock = true;// Options
if ( isset($product[1]) )
{
$options = unserialize(base64_decode($product[1]));
}
else
{
$options = array();
}
}
}
}
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
));