Using JSON sessions and foreach() statements - php

I've stumbled upon some problems while creating a shopping application. In short:
I'm using a php $_SESSION['cart'] to register all the products inside the cart
The products are registered and added to the cart by the following code:
else {// It's new: Add it to the array
$_SESSION['cart']['cartItems'][] = $cartProduct;
$_SESSION['cart']['totalItems']++;
}
To that function a cart with 2 or more products looks like this:
{"cartItems":[{
"id":"3",
"name":"Bedrukte Jurk",
"price":25.99,
"size":"L",
"quantity":"12",
"total_product_price":311.88
},
{
"id":"11",
"name":"Product voorraad id",
"price":144,
"size":"M",
"quantity":"23",
"total_product_price":3312
}
],
"totalPrice":3623.88,
"totalItems":2
}
So now i've got two questions regarding my $_SESSION['cart'];
How would i be able to delete a specific product. I was thinking about using the product id. And for now that has been working for me unless the unset($_SESSION['cart']['cartItems'] ... id part that i still haven't figured out. So how would i be able to tell php to delete the row with the requested id.
The second question is a bit more confusing to me since this has to do with writing the "cart" to the database on "payOrder" click.
So i've been struggling with this part and i've tried using a foreach() statement to get each row. But sadly only the first product is written in the database. The function handeling this foreach() is shown down below:
$cart_encode = json_encode($_SESSION['cart']['cartItems']);
$cartDecode = json_decode($cart_encode);
$date = date("Y-m-d h:i:s");
// Create the cart Using XML
$opt = $webService->get(array(
'resource' => 'carts',
));
// Define the $resource
$resource = $opt->children()->children();
// Adding the product items
foreach ($cartDecode as $key => $cartItem) {
$resource->associations->cart_rows->cart_row->id_product = $cartItem->{"id"};
$resource->associations->cart_rows->cart_row->id_product_attribute = 1;
$resource->associations->cart_rows->cart_row->id_address_delivery = 1;
$resource->associations->cart_rows->cart_row->quantity = $cartItem->{"quantity"};
}
Update after the comments
So as #Randall has mentioned it's better to use the product_id's as a new array index layer for deleting the row's in the cart, in this case a particulair product.
So i've edited my code to an older state in wich this is true and Question one is solved.
Anyhow the new JSON structure is:
{"cartItems": {
"5": {
"id":"5",
"name":"Bedrukte Zomerjurk",
"price":30.5,
"size":"L",
"quantity":"34",
"total_product_price":1037
},
"4": {
"id":"4",
"name":"Bedrukte Avond Jurk",
"price":50.99,
"size":"L",
"quantity":"3",
"total_product_price":152.97
}
},
"totalPrice":1189.97,
"totalItems":2
}
Still Question 2 sadly stays unanswered about the database input. I hope there are some people that could help me out.
PS: #Randall thanks for the "it makes no difference tip, it solved question 1 of the 2!".
I hope my question is clear and if it isn't please let me know.
As always,
Thanks in advance!

Related

Delete core_url_rewrite entry programmatically magento

I need to add redirect for 30 urls in 3 stores. For that I have created a script, using that I can add the urls, but the issue with the script is if the request path already exists I have to delete the entry and insert the new one. I have used the below code for that, it doesn't deletes the already existing entry(is_system=>1 for this entry). Can anyone help me solve this.
$rewrite_collection = Mage::getModel('core/url_rewrite')->getCollection();
$rewrite_collection->addFieldToFilter('request_path', array('eq' =>
$request_path));
$rewrite_collection->addFieldToFilter('store_id', array('eq' => 1));
$rewrite_collection_count = $rewrite_collection->count();
if($rewrite_collection_count < 0){
foreach ($rewrite_collection->getItems() as $rewrite){
$rewrite->delete();
}
}
Mage::getModel('core/url_rewrite')
->setStoreId(1)
->setIsSystem(0)
->setOptions('RP')
->setIdPath($id_path)
->setRequestPath($request_path)
->setTargetPath($target_path)
->save();
if($rewrite_collection_count < 0){
The above code, only check the count is less than zero.
Please change the code as
if($rewrite_collection_count > 0){
foreach ($rewrite_collection->getItems() as $rewrite){
$rewrite->delete();
}
}
Allow me to bring some ineteresting elements to the accepted answer, that you'll be able to use for all your future delete/save operations :
$transaction = Mage::getResourceModel('core/transaction');
foreach ($rewrite_collection->getItems() as $rewrite){
$transaction->addObject($rewrite);
}
$transaction->delete(); //or $transaction->save() when you need
This allows you to delete/save all the objects you give to the transaction object to be saved/deleted in only one SQL transaction, and roll it back if an error occurs (automatically done if an exception is raised during the save of one of the models).
Also, try to make a habit of calling your collections this way :
$rewrite_collection = Mage::getResourceModel('core/url_rewrite_collection');
instead of :
$rewrite_collection = Mage::getModel('core/url_rewrite')->getCollection();
Fewer steps.

Selecting and using JSON array values

I'm currently working on a shopping application but i stumbled upon a problem. The problem is that i can't select the JSON values from my "shopping cart". See the following code and description.
So by using add to cart buttons and such i'm creating the shopping cart. The shopping cart is actually a JSON object. An example of the cart:
{"cartItems":{"2":{"id":"2","name":"Blouse","price":26.99,"size":"M","quantity":"3","total_product_price":80.97},"5":{"id":"5","name":"Bedrukte Zomerjurk","price":30.5,"size":"L","quantity":"4","total_product_price":122}},"totalPrice":202.97,"totalItems":2,"customerSelect":{"id":"1","firstname":"John","lastname":"TestStefans"}}
As you can see the design of my JSON cart is:
cart:{"cartItems":{"id":{ product information }}}
The problem now is trying to select the values like the "name" and "price". This due to the "id"{ segment. But i need that piece for removing one item by id from the cart.
So my question is:
How would i be able to select all the product information and create an foreach for placing the information in the database / email template. I've been trying this but this only gave me the first product:
$cart_encode = json_encode($_SESSION['cart']['cartItems']);
$cartDecode = json_decode($cart_encode);
// Adding the product items
foreach ($cartDecode as $key => $cartItem) {
$resource->associations->cart_rows->cart_row->id_product = $cartItem->{"id"};
$resource->associations->cart_rows->cart_row->id_product_attribute = 1;
$resource->associations->cart_rows->cart_row->id_address_delivery = 1;
$resource->associations->cart_rows->cart_row->quantity = $cartItem->{"quantity"};
}
Take note that i'm using XML for database input. For the email template i've tried:
$testName = $_SESSION['cart']['cartItems']['name'];
$testPrice = $_SESSION['cart']['cartItems']['price'];
$testQuantity = $_SESSION['cart']['cartItems']['quantity'];
$testTotal = $_SESSION['cart']['cartItems']['total_product_price'];
$testProduct = array(
"Name:" => $testName,
"Price:" => $testPrice,
"Quantity" => $testQuantity,
"Total" => $testTotal
);
Iknow that the id number is missing but i cant dynamicly avoid that layer.
I hope that my question is clear
As always. Thanks in advance!

magento - retrieve values from catalog/eav_attribute

Ive added a field to catalog/eav_attribute and managed to save data into it. I just cant figure out how to get the data out in the front end.
im using the event observer "catalog_product_load_after" and im trying to extract "is_featured_attribute" from the "catalog/eav_attribute" resouce, im fairly new to magento and just cant figure out how to get the data.
Any help would be greatly appreciated
Dave
It would help if you could show what your observer function looks like, but I'll hypothesize. Essentially you need to load the product from the observer to retrieve your attribute value;
public function yourClass($observer) {
// Get the observed product
$item = $observer->getProduct();
// Get value of your attribute (guessing Yes or No)
$myAttr = $item->getIsFeaturedAttribute();
if($myAttr == 'Yes') {
// Do something
$isItYes = true;
} else {
// Do something
$isItYes = false;
}
return $isItYes;
}

Adding custom option to order line

I'm currently trying to add a custom option to a specific orderline on add to cart via the following:
public function addToPackageQuote()
{
$cart = Mage::getSingleton("checkout/cart");
$quote = Mage::getSingleton("checkout/session")->getQuote();
$packageId = Mage::getModel('MyTuxedo_OPP/Package')->checkPackageId();
$products = $this->sortArray();
foreach ($products as $productInfo) {
try {
$split = explode(",", $productInfo);
$_product = Mage::getModel('catalog/product')->load($split[0]);
if($_product->isConfigurable()) {
$simpleId = $this->getConfigurableSimple($split[1],$split[3],$split[0]);
} else {
$simpleId = $split[0];
}
$product = Mage::getModel('catalog/product')->load($simpleId);
$options = new Varien_Object(array(
"qty" => 1,
"custom_options" => array(
"package" => $packageId,
"packageName" => Mage::helper('MyTuxedo_OPP')->getPackageName()
)
));
$quote->addProduct($product, $options);
$this->_getSession()->setCartWasUpdated(true);
$quote->save();
} catch (Exception $e) {
echo $e->getMessage();
}
$this->addFreeItems();
}
$cart->save();
unset($_SESSION['products']);
unset($_SESSION['productId']);
$cart->save();
// Let's unset all the package sessions (apart from a few that are needed!).
$this->kill();
}
This method is completely seperate from the generic add to cart handler, and is used purely in a packages system so that it adds simple products exclusively (also breaks down configurables super attribute to find the simple product too).
These simple products have no custom options attached to them in the Magento backend, nor is it a goal to add custom options to the product itself. What I would like to do is attach custom options to the order-line that is then transferred over to the order if a purchase is made. So effectively data that is added at the add to cart method and no where else!
The add to cart method works as expected it's just not including the custom options I am trying to attach. I have also tried defining the options object as simply:
$options = new Varien_Object(array(
"qty" => 1,
"package" => $packageId,
"packageName" => Mage::helper('MyTuxedo_OPP')->getPackageName()
)
The above info, not including qty is not in the orderline object at all, and I can't seem to work out where to move on from here.
Endlessly googling at the moment so some help would be most appreciated!!
I do appreciate I’m instantiating the product model object twice in this, however the plan is to just get it working then optimise! :)
You have to set the custom options for the product before adding it to cart.
$product->setCustomOptions($options);
The in Mage_Sales_Model_Quote::_addCatalogProduct() the custom options will be added to the cart item.
See also here: http://www.magentocommerce.com/boards/viewthread/49659/
By the way: Your code may be pretty slow because you are loading products twice in a foreach loop. You should consider some refactoring by using the product collection instead. Also it looks kind of hackish to directly access the $_SESSION variable here. You could rather use the Checkout Session for that (Mage::getSingleton('checkout/session')).
I have now resolved this, after much headache. You can add a custom option to the cart and not have to instantiate the product object and save a custom option to do this, it can be done via tacking onto an observer, and pulling the quote items.
After tacking onto: sales_quote_add_item
I then used:
public function addCustomData($observer) {
$event = $observer->getEvent();
$quote_item = $event->getQuoteItem();
$quote = $session->getQuote();
$quote_item->addOption(array("product_id" => $quote_item->getProduct()->getId(),
"product" => $quote_item->getProduct(),
"code" => 'PackageId',
"value" => Mage::getModel('MyTuxedo_OPP/Package')->checkPackageId()
));
$quote->save();
}
It is most important to include the product object and id, as the function doesn't use the loaded object for some reason.
You can then get at the object via:
$_item->getOptionByCode('PackageId')->getValue();
Quick piece of handy info, if it dumps a stack trace in front of you it can't find the defined option, lose the getValue() (if using var_dump) function to see if you are getting a null value, otherwise xdebug will give you a ton of hints to get around it.

Why can't I see the database updates unless I refresh the page?

Hmmmmm I worked on some PHP code that pulls stock levels from my supplier and inserts the stock level into the database based on the product's SKU. I've inserted it into the class.product.php file which contains all the code used for the individual product page. The issue I'm having is that when the product page loads, it doesn't show the updated inventory levels unless you hit refresh. I've moved the code all over the place and can't get it to update the database and have the updated number loaded before the page is displayed.
Even when placed before all other code, I still have to refresh the page to see the update. I don't know what else to do about this. I feel like perhaps, I don't truly understand how PHP loads code. I've been working on this every day for weeks. I tried running it as an include file, on a separate page, at the top, in the middle, all over the place.
In the class file, it looks like I have the code before it calls the code to display the stock levels, that's why I'm so confused as to why it won't load the updates.
Any thoughts on why I'm unable to see the changes unless I refresh the page?
Thanks!
PHP loads the content when you request it ,
so opening a page gets the content ONCE,
The thing you want to do to get data updated is have AJAX calls to a php function that return data in JSON or XML format
Here you can see some examples but consider googling around for more detailed examples.
The problem was my code was not running until after the code to get and display the product data because I was using info from the product data that was only being called once. So the product data had be be called first in order for my code to run. So to fix this, I had to create a new function that would get the sku and pass it to my code before the code that called the product data to be displayed on the page. I copied the existing function to get the product data, renamed it to GetRealTimeStockLevels and added my code to the bottom of it. I put the call for the function above the call for the product data and it worked like I wanted. I'm glad I got this worked out, now I can add the same feature to the checkout page.
Below is the function call at the start of the page and then the function I created to run my update code.
public function __construct($productid=0)
{
// Get the stock level from supplier and update the database
$this->_GetRealtimeStockLevels($productid);
// Load the data for this product
$this->_SetProductData($productid);
public function _GetRealtimeStockLevels($productid=0)
{
if ($productid == 0) {
// Retrieve the query string variables. Can't use the $_GET array
// because of SEO friendly links in the URL
SetPGQVariablesManually();
if (isset($_REQUEST['product'])) {
$product = $_REQUEST['product'];
}
else if(isset($GLOBALS['PathInfo'][1])) {
$product = preg_replace('#\.html$#i', '', $GLOBALS['PathInfo'][1]);
}
else {
$product = '';
}
$product = $GLOBALS['ISC_CLASS_DB']->Quote(MakeURLNormal($product));
$productSQL = sprintf("p.prodname='%s'", $product);
}
else {
$productSQL = sprintf("p.productid='%s'", (int)$productid);
}
$query = "
SELECT p.*, FLOOR(prodratingtotal/prodnumratings) AS prodavgrating, pi.*, ".GetProdCustomerGroupPriceSQL().",
(SELECT COUNT(fieldid) FROM [|PREFIX|]product_customfields WHERE fieldprodid=p.productid) AS numcustomfields,
(SELECT COUNT(reviewid) FROM [|PREFIX|]reviews WHERE revstatus='1' AND revproductid=p.productid AND revstatus='1') AS numreviews,
(SELECT brandname FROM [|PREFIX|]brands WHERE brandid=p.prodbrandid) AS prodbrandname,
(SELECT COUNT(imageid) FROM [|PREFIX|]product_images WHERE imageprodid=p.productid) AS numimages,
(SELECT COUNT(discountid) FROM [|PREFIX|]product_discounts WHERE discountprodid=p.productid) AS numbulkdiscounts
FROM [|PREFIX|]products p
LEFT JOIN [|PREFIX|]product_images pi ON (pi.imageisthumb=1 AND p.productid=pi.imageprodid)
WHERE ".$productSQL;
if(!isset($_COOKIE['STORESUITE_CP_TOKEN'])) {
// ISC-1073: don't check visibility if we are on control panel
$query .= " AND p.prodvisible='1'";
}
$result = $GLOBALS['ISC_CLASS_DB']->Query($query);
$row = $GLOBALS['ISC_CLASS_DB']->Fetch($result);
if (!$row) {
return;
}
$this->_product = $row;
$this->_prodid = $row['productid'];
$this->_prodname = $row['prodname'];
$this->_prodsku = $row['prodcode'];
$GLOBALS['CurrentProductLink'] = ProdLink($this->_prodname);
$server_url = "http://ms.com/fgy/webservices/index.php";
$request = xmlrpc_encode_request("catalog.getStockQuantity", array($this->_prodsku));
$context = stream_context_create(array('http' => array(
'method' => "POST",
'header' => "Content-Type: text/xml",
'content' => $request
)));
$file = file_get_contents($server_url, false, $context);
$response = xmlrpc_decode($file);
$query = sprintf("UPDATE [|PREFIX|]products SET prodcurrentinv='$response' where prodcode='%s'", $GLOBALS['ISC_CLASS_DB']->Quote($this->_prodsku));
$result = $GLOBALS['ISC_CLASS_DB']->Query($query);
}

Categories