PHP - How to limit a foreach loop? - php

I have maybe some stupid question.
Here is my code:
$customers = Mage::getModel('customer/customer')
->getCollection()
->addAttributeToSelect('*')
->addFieldToFilter('group_id', $groupId);
$LimitLoop = 50;
foreach($customers as $customer)
{
$email=$customer->getEmail();
$CustomerPhone = $customer->getPrimaryBillingAddress()->getTelephone();
$CustomerName = $customer->getName();
$CustomerEmail = $customer->getEmail();
if($EnableSMSNotification==1 && $smstext!="") {
$api = new TextMagicAPI(array(
"username" => $TextMagicUsername,
"password" => $TextMagicPassword
));
// Use this number for testing purposes. This is absolutely free.
$phones = array($CustomerPhone);
$results = $api->send($smstext, $phones, true);
$write = Mage::getSingleton('core/resource')->getConnection('core_write');
$sql_insert = "insert into VivasIndustries_SmsHistory values ('','$CustomerName','$CustomerPhone','$CustomerEmail','$smstext',NOW())";
$write->query($sql_insert);
}
}
This is a simple foreach loop.
How can i limit it to the value pointed in $LimitLoop ?
How can i fetch only a limited number of results in this loop ?
Thanks in advance!

If using a for loop is out of the question then you would need to manually add an incrementing counter to perform the same logic. Something like this:
$LimitLoop = 50;
$i = 0;
foreach ($customers as $customer) {
if ($i++ >= $LimitLoop) {
break;
}
// the rest of the loop
}

you can save the variable $i from the other examples if you use something like this
$LimitLoop = 50;
foreach ($customers as $customer) {
/* your code to run */
/* ..... */
/* at the bottom */
$LimitLoop--;
if ($LimitLoop===0) {
break;
}
}

It's pretty simple:
$customers = Mage::getModel('customer/customer')
->getCollection()
->addAttributeToSelect('*')
->addFieldToFilter('group_id', $groupId);
$LimitLoop = 50;
$counter = 0; //Add a means of counting how many times it's been through the loop
foreach($customers as $customer)
{
$email=$customer->getEmail();
$CustomerPhone = $customer->getPrimaryBillingAddress()->getTelephone();
$CustomerName = $customer->getName();
$CustomerEmail = $customer->getEmail();
if($EnableSMSNotification==1 && $smstext!="") {
$api = new TextMagicAPI(array(
"username" => $TextMagicUsername,
"password" => $TextMagicPassword
));
// Use this number for testing purposes. This is absolutely free.
$phones = array($CustomerPhone);
$results = $api->send($smstext, $phones, true);
$write = Mage::getSingleton('core/resource')->getConnection('core_write');
$sql_insert = "insert into VivasIndustries_SmsHistory values ('','$CustomerName','$CustomerPhone','$CustomerEmail','$smstext',NOW())";
$write->query($sql_insert);
}
$counter++; //Increment the counter
if($counter >= $LimitLoop) break; //Break the loop if we have enough results
}

You'd either want to use a break statement or use a for loop that runs up to $LimitLoop.
For loop (I use array_keys function as $customers could be an associate array or have missing numeric keys, etc. Indexing the array of keys (which will have numeric ordering) then assures we always get the next key):
$keys = array_keys($customers);
for ($i = 0; $i < $LimitLoop; $i++) {
$customer = $customers[$keys[$i]];
// the rest of your code
}
Note: You would have to also insert some more logic to check that you do have 50 customers with the above loop as else it'll start throwing warnings about accessing invalid offsets in the array.
break:
$i = 0;
foreach ($customers as $customer) {
// your code
$i++;
if ($i >= $LimitLoop) {
break;
}
}

Related

how to use this function companiesContestRounds($companyNames,$successRate) as a loop but $successRate it divide /2 for each round

<?php
$companyNames =["Apple","Microsoft","Samsung Electronics","Alphabet","AT&T","Amazon","Verizon Communications","China Mobile","Walt Disney","Facebook",
"Alibaba","Intel","Softbank","IBM","Tencent Holdings","Nippon Telegraph & `enter code here`Tel","Cisco Systems","Oracle","Deutsche Telekom","Taiwan Semiconductor"];
$successRate = 50;
// working
function generateCompanyRates($companyNames){
$companyRates = [];
foreach ($companyNames as $name){
$companyRates[$name] = rand(0,100);
}
return $companyRates;
}
function companiesContestRounds($companyNames,$successRate){
$companiesRate = generateCompanyRates($companyNames);
$successCompanies = [];
foreach ($companiesRate as $companyName => $Rate){
if($Rate <= $successRate){
$successCompanies[] = $companyName;
}
}
return $successCompanies;
}
function successfulCompanies($companyNames, $successRate){
}
use loop inside function successfulCompanies($companyNames, $successRate) and $successRate/2 for each round until we have one company left that is the winner
really i'm stuck
<?php
//Enter your code here, enjoy!
$companyNames =["Apple","Microsoft","Samsung Electronics","Alphabet","AT&T","Amazon","Verizon Communications","China Mobile","Walt Disney","Facebook",
"Alibaba","Intel","Softbank","IBM","Tencent Holdings","Nippon Telegraph & Tel","Cisco Systems","Oracle","Deutsche Telekom","Taiwan Semiconductor"];
$successRate = 50;
function successfulCompanies($companyNames,$successRate){
$associativeArray = [];
$finalArray = [];
foreach($companyNames as $names){
$associativeArray[$names] = rand(0,100);
}
foreach($associativeArray as $company => $rate){
if($rate <= $successRate){
$finalArray[] = $company;
}
if($rate > $successRate){
}
}
print_r($finalArray);
}
Then it loops over the companyName
○ For each iteration of the loop it does the following
■ Generate a random number from 0 to 100
■ Store each random value along with its company name in an associative
array

how to sort an array in descending order in php

Newly-entered products are displayed in the last row. If there is a large amount, it is difficult to see at the bottom. How can I change the new display to the top. Thank you!
$barcodes_ary = explode(',', $barcodes);
$barcodes_hash = array ();
foreach ($barcodes_ary as $b) {
if (array_key_exists($b, $barcodes_hash)) {
$barcodes_hash[$b] += 1;
} else {
$barcodes_hash[$b] = 1;
}
}
foreach ($barcodes_hash as $b => $amount) {
if ($barcodes_ary == array(''))continue;
$ary = get_sql("SELECT * FROM Products WHERE Barcode='$b' Order by ProductName");
if ( count($ary) == 0 ) {
continue;
}
$pid = $ary[0]['ProductID'];
$pn = $ary[0]['ProductName'];
$unit = $ary[0]['UnitID'];
$ary2 = get_sql("SELECT UnitName FROM Units WHERE UnitID = '$unit'");
$unit = $ary2[0]['UnitName'];
?>
<TR>
<TD><? echo "$pn"; ?></TD>
<TD>
<INPUT TYPE=hidden NAME=productid<?=$pid?> VALUE='<?=$pid?>'>
<?
$candidates = array();
for($i=1; $i <= DropDownMaxValue; $i++) {
$candidates[]=$i;
}
//update
I use another way to solve the problem. Just display the same product.
function push_barcode() {
// alert('barcode pushing');
b = document.form1.barcode;
bs = document.form1.barcodes;
if (bs.value == "") {
bs.value = b.value;
} else { // ?? 111,333,444,... ???
bs.value = b.value;
}
}
Okay, you should be able to get the count using the keys values returned in reverse in brackets with the array.
Try the following and see if it works for you...
$ProductName = $ary[0]['ProductName'];
//--> get the count of your array
$count = count($ProductName);
//--> define an output variable to hold values
$output = null;
$i = 0;
//--> reduce count by one as key values start at 0 and count starts at 1
$count = $count - 1;
//--> subtraction and addition of $count by one to reduce warning
//--> of `undefined offset` for index on mismatched key values
while($count + 1){
//--> concatenate the values into a variable for display
$output .= $ProductName[$count];
//--> or push the reversed values back into an array
$product_name[$i] = $ProductName[$count];
//--> $product_name should now hold your values in reverse use a foreach
// use a foreach to display values in your table
$count--;
$i++;
}

PHP Shopware Rest API - How to sum specific Keyvalues of Arrays in an Array

I want to calculate and show the turnover of some webshops(Plattform:Shopware), filtered by month and without canceled orders.
I got the connection to the webshop, I already got all orders, sorted them by month, filtered out the canceled orders. Now I pushed all relevant orders into a new array called $october. In $october, every single order is an array itself with many keys and values. I just need to summarize all "invoiceAmount" values together so i can show the turnover of this month. I tried many variations(commented), the best i get is "0" from the initialization of $sum... but im also very new to php. please help me out :-)
API Resources Orders
<?php
include_once ('api.php');
$url = xxxxx;
$user = xxxxx;
$key = xxxxx;
$client = new ApiClient($url,$user,$key);
$orders = $client->get('orders');
$october = [];
echo "<h1>===================month Array==============</h1>";
foreach ($orders as $order) {
foreach ($order as $field) {
if ($field["orderStatusId"]!==4) {
$mystring = $field[orderTime];
$findme = '-10-';
$pos = strpos($mystring, $findme);
if ($pos !=null) {
print_r($field);
array_push($october,$field);
}
}
}
}
echo "<script>";
echo 'console.log('.json_encode($october).')';
echo "</script>";
print_r($october);
echo("<h1>===================Sum of month==============</h1>");
$sumOctober = 0;
foreach ($october as $field["invoiceAmount"]=>$value) {
$sumOctober+= $value;
}
/*
$sumOctober = 0;
foreach ($october as $order) {
foreach ($order as $field["invoiceAmount"]=>$value) {
$sumOctober+= $value;
}
}
*/
echo($sumOctober);
/*
$arr = $october;
$sum = 0;
foreach ($arr as $order){
foreach ($order as $field["invoiceAmount"]=>$value) {
$sum += $value;
}
}
*/
/*
$arr = $october($orders($key));
$sum = 0;
array_walk_recursive($arr, function($val, $key) use (&$sum) {
$sum += $val;
});
var_dump($sum);
echo "<h1>Die Summe Oktober ist:</h1>";
echo ($sum);
*/
?>
This totally helped, dont know why the guy deleted his answer right away...but thanks!
$sumOctober = 0;
foreach ($october as $oct) {
$sumOctober+= $oct["invoiceAmount"];
}

How to store product quantities in an array

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.

how to know if an array of indexed arrays had the same value more than once?

I have this array
$products[0]['productid'] = 5;
$products[0]['name'] = "apples";
$products[0]['seller'] = 1;
$products[1]['productid'] = 15;
$products[1]['name'] = "orange";
$products[1]['seller'] = 1;
$products[2]['productid'] = 5;
$products[2]['name'] = "apples";
$products[2]['seller'] = 2;
// .... more 5000 products
this array is filled by the client with ajax. I need to make a restriction that $products array don't have the same productid in any of it's other members. as in the invalid data example above 5
What I do to get that done is by doing this
$onlyids = array();
for($x=0; $x < count($products); $x++){
$onlyids[]=$products[$x]['productid'];//get only productid in an array
}
//remove duplicate members
$onlyids2= array_unique($onlyids);
//check if there were duplicates
if(count($onlyids) != count($onlyids2)){
//same id found, reject client inputs
}
did I do it correct ? or there is a better performing way. because my way is obviously consume more time on big arrays?
Probably the most performant way is to store found product ids as array keys while you iterate the data:
$productIds = [];
foreach ($products as $product) {
if (isset($productIds[$product['productid']])) {
throw new Exception('Duplicate product id ' . $product['productid']);
}
$productIds[$product['productid']] = true;
}
echo 'All good';
More obscure and inefficient, but a one-liner:
if (max(array_count_values(array_column($products, 'productid'))) > 1) {
throw new Exception('Invalid input');
}

Categories