Specifying a true/false result in foreach loop - php

I apologize ahead of time for the crappy question title I couldnt figure out a good way to summarize the solution Im looking for in a sentence.
Platform is Magento/PHP but the Magento part isnt really a part of this problem. Basically we have a service at checkout (just a dropdown box) for customers to select a future date for their order to ship. Ive been tasked with limiting the display of this service to only a few products.
If an order contains one or more of a permitted product, or, several of the products that are permitted it would display the dropdown box.
If the order contains a mix of permitted and non-permitted products obviously it would not show the dropdown box.
I created a new product attribute called "can_futureship" and set the value to True for the few products that are permitted to ship on a future date. My problem now is I cant seem to grasp the best way to single out those products.
There is a chunk of code (foreach loop) that goes through all the items in the cart and checks them for other restrictions and attributes so I know I need to put it in that loop. Especially in the cases of mixed True and False conditions. For example some pseudocode:
Product1 = True
Product2 = True
Product3 = True
$can_futureship_show_drop_down = false;
foreach(Items as item) {
$product['can_futureship'] = model->getattribute('can_futureship');
if ($product['can_futureship'] = TRUE) {
$can_futureship_show_drop_down = true;
}
}
That was my initial line of thinking and would obviously work if all the products are true or the last product in the array is true but I need it to end up false if there any false results at all. I was also thinking that maybe I should load all results into an array and check for false results that way? Any help is greatly appreciated!

Think the other way ;)
$can_ship_future = true;
foreach($products as $product) {
if ( ! $product->canShipFuture() ) {
$can_ship_future = false;
break; // Don't need to check the other products
}
}

Related

Edit WC shipping method on orders

I want to simply change the shipping method of an order on Woocommerce.
I have seen a few posts on editing shipping methods on orders but I'm not 100% clear on the exact protocol of how it works, I have a rough idea but no success yet! If you can help me to get the order to update its shipping method that would be awesome! (this is the middle of a large project so I can't share the whole plugin, let me know if you need anymore details happy to provide anything that's necessary!)
I have this small bit of code that returns me a list of orders that need shipping method updated and the new shipping method rateID that it has to be changed to, that all works fine but i have included it so you can see where it comes from.
Once the array of orders to be updated has been constructed, it then needs to be processed using the set_shipping() method. One at a time working through the array items and updating the shipping method of each, from the original to the new one provided in the toUpdate array
UPDATED: i have tried using the WC_API_Orders() class as set_shipping is a method of that. still coming up with the unrecognised error.
'Class 'Inc\Api\Callbacks\WC_API_Orders' not found'
private function updateRound()
{
if (! empty($_POST['update'])) {
$updateorderID= $_POST['orderID']; //get list of orderID to change
$updateRound= $_POST['newRound']; //list of rounds new orders want swapped to
$updateList= $_POST['update']; //uses a check box to confirm user wants to update row (stops accidentally updating the whole list)
// print_r($_POST['update']); //shows an output to check results.
$toUpdate = []; //this is the array for all the shippingmmethods to update on set order etc.
//make list of order ID's to update and their new shipping method
foreach ($updateList as $key => $value) {
$toUpdate[] = [
'orderID' => $key,
'newRound' => $updateRound[$key]
];
}
}
$absOrder = new WC_API_Orders();
foreach ($toUpdate as $updateOrder) {
//echo "</br>OrderID: ".$updateOrder['orderID']." Round updated to ".$updateOrder['newRound'];
echo "order ".$updateOrder['orderID']."updating";
$absOrder->wc_get_order($updateOrder['orderID']);
echo " order retreived";
$absOrder->set_shipping($order, $updateOrder['newRound'], 'update' );
echo "updated </br>";
}
}
This is for a very local veg delivery scheme, people can only place an order if their postcode is in the set group, so that's not so important, this shipping method we use to change from 'wed round' to 'thurs round' etc. Simple really no concern for delivery companies etc, its all in house. Tax etc. doesn't matter, it's all done elsewhere, this is simply meant to be a way of editing orders onto delivery rounds.

Hide Stock Qty/Availability for Specific Attribute Set

I have a bit of an odd situation that I am trying to fix. Magento v1.9.2.4
I have only 2 different attribute sets. A and B.
I want to display the stock quantity/availability for set B, but not
set A.
To make things a bit more complex, I have 14 Customer Groups, I only want 6 of those groups to ever see any quantities/availability.
Here's what I have done so far to arrange this:
$customerSession = Mage::getSingleton('customer/session');
if($customerSession->isLoggedIn()){
$groupId = $customerSession->getCustomerGroupId();
$group = Mage::getModel('customer/group')->load($groupId);
if ('custgroup_1' == $group->getCode()){
$qty = (int) Mage::getModel('cataloginventory/stock_item')->loadByProduct($_product)->getQty();
echo 'Quantity Available: ' . $qty;
}
}
The above snippet is repeated 5 times with the [if ('custgroup_1' ...] changed to accommodate the group I need this to show up for. That part is working just fine.
I only need to specify somehow that I only want the availability to show up for the attribute set B. Then Regardless of the customer group never show the qty/availability for attribute set A.
I have tried playing with the inventory options on the product page. (disabled stock management = qty still shows | enabled stock management, set qty to 0 and my custom options disappear | ect.) Nothing within the magento backend seems to work.
I'm a newbie to this whole Magento/Dev thing. So I apologize if this is considered a silly question.
Thank you for any/all help!
So, Immediately after posting this I realized I was thinking about the problem all wrong.
Because any item that isn't in attribute set B isn't having stock managed, I was able to write a condition that enables output only for products that have an inventory level greater than 0.
Here is the code for anyone who might happen to need to show a quantity for products based on a customer group, and hide availability for any item that has inventory management set to no, but is set to "In Stock".
$customerSession = Mage::getSingleton('customer/session');
if($customerSession->isLoggedIn()){
$groupId = $customerSession->getCustomerGroupId();
$group = Mage::getModel('customer/group')->load($groupId);
if ('custgroup_1' == $group->getCode()){
$__manStock = $_product->getStockItem()->getManageStock();
$__invAmt = (int)Mage::getModel('cataloginventory/stock_item')->loadByProduct($_product)->getQty();
if ($__manStock > 0)
echo $this->__("Available Qty: $__invAmt");
}
}

Adding products that already in $_SESSION array

I have a tiny problem with adding products into global array. This may be used in shop cart. Here is the part of code that we focus in:
if ( isset($_POST['id']) ){ // If the product is adding to cart. This product Id is sended via form.
$productid = mysql_real_escape_string($_POST['id']);
$cartproduct = mysql_query("select * from stuff where id = '$productid'");
$Addrow=mysql_fetch_assoc($cartproduct);
if ($Addrow['qty']<$_POST['qty']){ // the product quantity that will add to cart can't be greater than in database
$_POST['qty']=$Addrow['qty'];
}
$new_product = array(array('name'=>$Addrow['name'], 'id'=>$Addrow['id'], 'price'=>$Addrow['price'], 'qty'=>$_POST['qty'])); // Creating new product info in array
if (isset($_SESSION['cart'])){ // If the cart exist
foreach ($_SESSION['cart'] as $add_product){
if ($add_product['id']==$_POST['id']){ // checking that product is already in $_SESSION
$exist = TRUE;
}else{
$exist = FALSE;
}
}
if ($exist == TRUE){ // If The product is in the $_SESSION: Update amount
// I dont have code for it.
}else{ // The product is not in array, add it.
$_SESSION["cart"] = array_merge($_SESSION["cart"], $new_product);
}
}else{ // If the cart is not exist
$_SESSION['cart']=$new_product;
}
}
And the problem is when I try to add the product that already in array. The function is adding it as new product...
The second problem is with remove these products. I can't do this using this:
foreach ($_SESSION['cart'] as $remove){
if($_GET["id"] == $remove['id']){
unset($_SESSION["cart"][$remove]);
}
}
Anyone can help to solve it?
I would suggest to change the array a bit. Inside 'cart', use the product id as a key for the products. That way, you can easily find and update products in the array.
You can just change the cart array in the session. Because keys are unique in the array, setting a value for the key will overwrite the previous one.
So I've added a slightly modified version of your inner piece of code. It performs three steps:
Add the post variables to normal variables. I find this easier to work with, and you can do all kinds of other checks before continuing (like checking if quantity > 0 etc).
Get the existing product from the array or initialize a new product. This uses array_key_exists, because I think that's the purest check, but people also use isset($_SESSION['cart'][$productId]), which should also work. Anyway, such a check is better (faster, easier) than using a loop, but it will only work if you switch to using product ids for the keys.
Simply set or update the quantity and write the updated prodct back into the array. If the product existed before, it will just overwrite the previous value.
Code becomes:
// Use a variable. It's easier and more readable.
$productId = $_POST['id'];
$quantity = $_POST['qty'];
// Your other checks go here. Left out for brevity.
// Get the current product from the cart, if it exists.
// If not, create a new product.
if (array_key_exists($productId, $_SESSION['cart'])) {
// Product found, get it and update its quantity.
$product = $_SESSION['cart'][$productId];
$product['qty'] += $quantity;
} else {
// Product not found. Initialize a new one.
$product = array(
'name' => $Addrow['name'],
'id' => $Addrow['id'],
'price' => $Addrow['price'],
'qty' => $quantity);
}
// Write updated or new product back to the array, and use the product id as key.
$_SESSION['cart'][$productId] = $product;
Some other tips:
Don't use the mysql_* functions if you have the opportunity to switch to mysqli or PDO. The mysql functions are deprecated.
Make sure to check the query result. Maybe something went wrong (or someone forged a request), and the product id cannot be found in the database. In that case, $Addrow will probably be false or null. Make sure to check for this and display an appropriate error instead of updating cart, possibly corrupting your cart.
If the quantity cannot be added, I wouldn't silently lower the quantity, because the user will think they found a bug. Instead, clearly state that such a quantity is not available.
And you may want to reconsider that. After all, maybe other stock will be delivered today, or other people might order the last item simultaneously. So it's better to check it later, when the order is well saved and you want to process it.
Showing information about available quantities in the cart will give your competition insight in the amount of stock you have, from which they can deduce other information too. Also, they may even place fake orders to make products unavailable on your website. It's a dog-eat-dog world. Be careful what information you show.

How to get random products if I don't have related products in magento

I have an issue. I want to show 4 related products in the product page. That is simple and I have done that. But if the product doesn't have any or has less than 4 products I want the remaining product to randomly appear in the page.
To select 4 random products first you need rewrite class that responsible for related block (or just move this file to local folder) and change logic for function that returns collection to something like next code:
$productsCollection = Mage::getResourceModel('catalog/product_collection');
$productsCollection->getSelect()->order('rand()');
$productsCollection->getSelect()->limit(4);
Hope, it will be helpful
If you're only interested in creating this functionality on the product page you can find most of the magic in Mage_Catalog_Block_Product_List_Related::_prepareData().
To fill out your related products with random products, we first need to know exactly how many random products we'll need. In this case, it's (4 - related products found):
// Existing Magento code near end of method
$this->_itemCollection->load();
// Our code
$numRandomsToGet = 4 - count($this->_itemCollection);
Then we can fetch the appropriate number of random products and add them to the collection:
// Our code
$randCollection = Mage::getResourceModel('catalog/product_collection');
Mage::getModel('catalog/layer')->prepareProductCollection($randCollection);
$randCollection->getSelect()->order('rand()');
$randCollection->addStoreFilter();
$randCollection->setPage(1, $numRandomsToGet);
$randCollection->addIdFilter($this->_itemCollection->getAllIds(), true);
foreach($randCollection as $randProduct)
{
$this->_itemCollection->addItem($randProduct);
}
// Existing Magento code
foreach ($this->_itemCollection as $product) {
$product->setDoNotUseCategoryId(true);
}
return $this;
Caveat/Plug: I pulled this code from our Related Products Manager extension for Magento so there might be some fiddling external to this method that needs to get done but I don't think so. If you get stuck you can try downloading the extension and examining the code in its entirety. Or, of course, you can just use the extension as-is.

Creating configurable product programmatically

I'm trying to create configurable products programmatically in Magento 1.5.1.
I understand I need first to create simple related products, what I did. Now I manage to associate these simple products to make a configurable one.
Here is the critical part...
I keep the ids and some of the attributes values in an array, so I can later make my configurable product, but some of them are missing, I don't know which method to call.
I found this entry in Magento Wiki, that helped me and seems to fit my needs.
However, at the end the author is setting two things :
$product->setConfigurableProductsData($data);
$product->setConfigurableAttributesData($data);
and the values in the arrays have been taken in the admin page source using Firebug....and then translated into PHP arrays (array example for the first call) :
"I’ve harcoded the values for my associated products and attribute
data. You can get attribute data by viewing the source through the
admin interface and using Firebug for Firefox."
$data = array('5791'=>array('0'=>array('attribute_id'=>'491', // I already got this
'label'=>'vhs', // this too
'value_index'=>'5', // but what is value_index ?
'is_percent'=>0,
'pricing_value'=>'')),
'5792'=>array('0'=>array('attribute_id'=>'491',
'label'=>'dvd',
'value_index'=>'6',
'is_percent'=>0,
'pricing_value'=>'')));
My question is : is there a way to retrieve these values without using Firebug (which in my script won't help me a lot !), but programmatically. I already found a way to retrieve attribute values, labels, etc... using its code, but one field I don't know is value_index.
I guess this may be the option position in an option list, but not sure.
Also if someone knows a good/better way to create a configurable product in Magento, please tell me.
Any help is welcome thank you.
It seems you're asking where to retrieve the value_index value where you already have the label. Here's what I had: I didn't test this on 1.5x.
function get_attribute_id($option, $type) {
$attributeId = Mage::getResourceModel('eav/entity_attribute')->getIdByCode('catalog_product', $type);
$attribute = Mage::getModel('catalog/resource_eav_attribute')->load($attributeId);
$attributeOptions = $attribute->getSource()->getAllOptions();
foreach ($attributeOptions as $opts_arr) {
if (strtoupper($opts_arr['label']) == strtoupper($option)) {
return $opts_arr['value'];
}
}
return FALSE;
}
$value_index = get_attribute_id('vhs', 'media_format');
No one else seemed to mention the easiest way to figure out what the value_index of vhs is: In the backend, under
Catalog > Manage > media_format > Manage Label/Options
Inspect the source of the individual form inputs. Where you have 'vhs' you should have an input named option[value][6]
As far as I understand your question, there are two options: a) create simple products by script, put the generated id's in an array and create the configurables using the ids or b) read the id's from the admin and put them in your script. Since programming is about automation I'd definately go for option a.

Categories