Why is this foreach loop iterating twice? - php

Question's in the title really - I have this foreach loop and it appears to be iterating over my array twice.
ob_start();
$array = str_split(strtolower($_GET['text']));
foreach ($array as $char) {
error_log($_GET['text'] . ', ' . sizeof($array) . ', ' . $char);
}
$result = ob_get_contents();
I am finding the code above is producing the following log when passing in the URL like so: index.php?text=Hi
[22-Oct-2018 20:05:37 Europe/London] Hi, 2, h
[22-Oct-2018 20:05:37 Europe/London] Hi, 2, i
[22-Oct-2018 20:05:37 Europe/London] Hi, 2, h
[22-Oct-2018 20:05:37 Europe/London] Hi, 2, i
The debug shows the array to only be 2 long, so I'm really not sure what it could be. Thanks!
After more debugging, I have found the following:
if (!isset($_GET['text'])) {
header('HTTP/1.0 404 Not Found');
die();
}
echo uniqid() . '</br>';
//ob_start();
$total = 0;
$array = str_split(strtolower($_GET['text']));
foreach ($array as $char) {
echo $_GET['text'] . ', ' . sizeof($array) . ', ' . $char . '</br>';
}
//$result = ob_get_contents();
echo $result;
Produces this:
5bce311d3d6bd
Hi, 2, h
Hi, 2, i
But un-commenting the two commented out lines, gives me this:
5bce313b9f29d
Hi, 2, h
Hi, 2, i
Hi, 2, h
Hi, 2, i

I think I perhaps have more to learn about the ob_... functionality?
This following code seems to be consistent and reliable:
if (!isset($_GET['text'])) {
header('HTTP/1.0 404 Not Found');
die();
}
echo uniqid() . '</br>';
ob_start();
$total = 0;
$array = str_split(strtolower($_GET['text']));
foreach ($array as $char) {
echo $_GET['text'] . ', ' . sizeof($array) . ', ' . $char . '</br>';
}
ob_flush();

Related

Inserting count and sum functions

Here is what my code prints:
Even numbers: 2 4 6
Here is my PHP code:
$names = file('file.txt');
echo "Text: ";
foreach($names as $name)
{
echo $name . "</br>";
}
echo "Even numbers: ";
foreach ($names as $name) {
$name = count_chars( $name, 3);
for($i=0; $i<strlen($name);$i++) {
if (is_numeric($name[$i]) && $name[$i]%2==0)
{
echo $name[$i];
}
}
echo "<br>";
}
?>
Could someone tell me how should I count all of these values into the new line (I need to get an answer 3) and get those values sum (I need to get 12)? I know I have to use count and sum functions, i don't know exactly where. Thanks for any help. All the answer should look like this:
Even numbers: 2 4 6
Even numbers are: 3
Even numbers sum are: 2 + 4 + 6 = 12
I don't really understand what your question.
But I think array_sum is what you are looking for. (https://secure.php.net/manual/en/function.array-sum.php)
Below is my code for your reference:
$array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
foreach($array as $key => $value) {
if (empty($value%2)) {
$even[] = $value;
} else {
$odd[] = $value;
}
}
echo 'Even numbers: '.implode(' ', $even).'<br>';
echo 'Odd numbers: '.implode(' ', $odd).'<br>';
echo 'Even numbers sum are: '.implode(' + ', $even).' = '.array_sum($even);
Try this :
$names = file('file.txt');
echo "Text: ";
foreach($names as $name)
{
echo $name . "</br>";
}
echo "Even numbers: ";
foreach ($names as $name) {
$count = 0
$evens = [];
$name = count_chars($name, 3);
for($i=0; $i<strlen($name);$i++) {
if (is_numeric($name[$i]) && $name[$i]%2==0)
{
$count++;
$evens[] = $name[$i];
echo $name[$i];
}
}
echo "<br>";
}
echo "Even numbers Are: " . $count;
$i=0;
foreach($evens as $e){
$i++;
if($i == count($evens)){
$evens_string .= $e . '=' ;
} else {
$evens_string .= $e . '+' ;
}
}
$even_string .= array_sum($evens);
echo "Even numbers sum are: " . $even_string;
Hope this gives you the idea! I have not tested the code.

PHP Place text (title) before each array category

This function is supposed to echo all singles and doubles numbers. (eg. 01 - 01 02).
I am trying to place a title before each 'category' using the code below and it is not working properly.
It should be something like this
SINGLES
01,02,03
DOUBLES
01 02, 03 04, 05 06
Can you help me fix this? Thanks!
function check_stats($todas){
$arrlength = count($todas);
for($x = 0; $x < $arrlength; $x++) {
$arrlength2 = count($todas[$x]);
if($arrlength2==1){
echo 'single'.'</br></br>';
list($a) = explode(" ", implode(" ", $todas[$x]));
echo $a; echo '</br>';
}
if($arrlength2==2){
echo 'double'.'</br></br>';
list($a,$b) = explode(" ", implode(" ", $todas[$x]));
echo $a.' '.$b; echo '</br>';
}
} //for
} //function
You are trying to separate singles and doubles. And you want to print them separately. You can't print them separately while you haven't detected them all. Then you need to detect all categories and after that you can print them separately. To do this you should save categories on detection and after detection print saved categories.
function check_stats($todas){
$singles = array(); // an array to save single numbers
$doubles = array(); // an array so save doubles
foreach ($todas as $toda) { // cleaner and beautifier than for
if (count($toda) == 1) { // direct compare without extra $arrlength2
$singles[] = $toda[0]; // will push $toda[0] to $singles array
} else if (count($toda) == 2) { // when put else compares less
$doubles[] = $toda[0] . ' ' . $toda[1];
}
}
// then you can do whatever with $singles and $doubles
echo 'SINGLES' . PHP_EOL;
foreach ($singles as $single) {
echo $single . PHP_EOL;
}
echo 'DOUBLES' . PHP_EOL;
foreach ($doubles as $double) {
echo $double . PHP_EOL;
}
}
Edit #1:
If there were more than 2 kind of variables, then you can keep them in an array.
function check_stats($todas){
$result_array = array();
foreach ($todas as $toda) {
$result_array[count($toda)] = implode(' ', $toda);
// the above code will save each single or double or triple or etc
// in an index in their size
}
return $result_array; // better return it and use out of function
}
$result = check_stats($todas);
// now print them
foreach ($todas as $key => $toda) {
echo $key . PHP_EOL; // print count (that is index)
foreach ($toda as $t) {
echo $t . PHP_EOL;
}
}

Recursive function return appears different in calling script.

I am testing the contents of the array, $list, I will return as I cycle through these recursive function calls.
There is a hard limit of 25 records to be fetched at a time.
On calls where the result set is equal to the limit I increment an offset and recurse sending the current array of results as an argument.
From inside these loops I dump the $list var and other details into an email indicating whether recursing or returning and the current counts and a dump of the $list array.
These emails contain exactly what I expect numbers-wise and in $list.
The calling script however seems to get a different $list containing only the last loop. In cases where the result set is over 25 $list is empty. If the whole set is under 25 it is correct in the calling script output.
Can someone please straighten me out on why $list seems different inside the function than it is after it returns?
Calling script:
$levels = get_membership_levels();
if ($levels) {
foreach ($levels as $l) {
echo "<h2>$l</h2>\n";
$members = get_current_members_by_level($l);
echo '<h2>' . count($members) . '</h2>';
Function:
function get_current_members_by_level($level, $offset = 0, $list = array()) {
require_once $_SERVER['DOCUMENT_ROOT'] . '/wp-content/plugins/civicrm/civicrm.settings.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/wp-content/plugins/civicrm/civicrm/CRM/Core/Config.php';
$config = CRM_Core_Config::singleton( );
require_once $_SERVER['DOCUMENT_ROOT'] . '/wp-content/plugins/civicrm/civicrm/api/api.php';
$result = civicrm_api3('Membership', 'get', array(
'membership_type_id' => "$level",
'limit' => 1000,
'offset' => $offset,
'api.Contact.get' => array(array('limit' => 1000, 'sort' => 'last_name')),
));
if ($result['values']) {
foreach ($result['values'] as $k => $v) {
$member = get_member($v['contact_id']);
if ($member) {
$list[]= $member;
}
}
if (count($result['values']) >= 25) {
$offset+= 25;
mail('email#example.com', "Recursing for $level - current set= " . count($result['values']) . ' Total: ' . count($list) . ' Offset= ' . $offset,print_r($list,1));
get_current_members_by_level($level, $offset, $list);
} else {
mail('email#example.com', "Returning result for $level - current set= " . count($result['values']) . ' Total: ' . count($list) . ' Offset= ' . $offset,print_r($list,1));
return $list;
}
}
}
I think the problem in your code is that you dont use the return or your function get_current_members_by_level();
if (count($result['values']) >= 25) {
$offset+= 25;
mail('email#example.com', "Recursing for $level - current set= " . count($result['values']) . ' Total: ' . count($list) . ' Offset= ' . $offset,print_r($list,1));
get_current_members_by_level($level, $offset, $list); // this function return the list but you dont use it.
} else {
mail('email#example.com', "Returning result for $level - current set= " . count($result['values']) . ' Total: ' . count($list) . ' Offset= ' . $offset,print_r($list,1));
return $list;
}
this should be instead
if (count($result['values']) >= 25) {
$offset+= 25;
mail('email#example.com', "Recursing for $level - current set= " . count($result['values']) . ' Total: ' . count($list) . ' Offset= ' . $offset,print_r($list,1));
$list = get_current_members_by_level($level, $offset, $list); // now the new list will be in the var $list
} else {
mail('email#example.com', "Returning result for $level - current set= " . count($result['values']) . ' Total: ' . count($list) . ' Offset= ' . $offset,print_r($list,1));
return $list;
}

Invalid values from cookies after explode/list()

setcookie("mnau", "1-445 1-51 1-3001");
$kosik = explode(" ", $_COOKIE["mnau"]);
foreach($kosik as $value) {
list($item_ajdi, , $itemcount) = $value;
echo $item_ajdi . " : " . $itemcount . ",";
}
Returns values 1 : 4, 1 : 5, 1 : 3, instead of 1 : 445 etc.
I think you just need to loop in your exploded array and then replace - with :
setcookie("mnau", "1-445 1-51 1-3001");
//var_dump($_COOKIE);
$kosik = explode(" ", $_COOKIE["mnau"]);
foreach ($kosik as $value) {
echo str_replace('-', ':', $value) . ', ';
}
This will output
1:445, 1:51, 1:3001,
#Fabio's answer is the best, but if you want to keep you current code, you need to do what #Caramiriel recommends and explode $value on -, to make it an array before using it in list().
setcookie("mnau", "1-445 1-51 1-3001");
$kosik = explode(" ", $_COOKIE["mnau"]);
foreach($kosik as $value) {
$value = explode("-", $value);
list($item_ajdi,$itemcount) = $value;
echo $item_ajdi . " : " . $itemcount . ", ";
}
with output
1 : 445, 1 : 51, 1 : 3001,

Foreach and columns

<?php
$arr = range(1,rand(40,120)); ?>
<table>
<?php
foreach ($arr as &$value) {
echo '<tr><td>' . $value . '</td></tr>';
} ?>
</table>
This generate for me for example:
1
2
3
...
111
all in one columns. How can i make - when in first column are 25 rows then create new column, etc. For example:
1 26 51
2 27 ...
3
..
25 50
How can i make it?
I can use DIV instead of table.
<?php
$arr = range(1,rand(40,120));
?>
<div style="width:40px; float:left;">
<?php
foreach ($arr as $value) {
echo $value . '<br />';
if ($value % 25 == 0) {
echo '</div><div style="width:40px; float:left;">';
}
}
?>
Vertically sorted columns of that sort (no pun intended) are a serious pain in html, since this arragement is a "top->bottom, left->right", while HTML tables by their nature are "left->right, top->bottom" instead.
To get around it, you have to do some offset math on the array indexes, so you can output by rows:
$arr = range(1,rand(40,120));
$rows = ceil(count($arr) / 3); // assuming 3 columns
for ($i = 0; $i < $rows; $i++) {
echo <<<EOL
<tr>
<td>{$arr[$i]}</td> 1, 2, 3, etc...
<td>{$arr[$i+rows]}</td> 11, 12, 13, etc...
<td>{$arr[$i+(2*$rows)]}</td> 21, 22, 23, etc...
</tr>
EOL;
}
This code probably won't work as is, but should give you the basic idea.
EDITED
<?php
$rows = 25;
$arr = range(1, rand(40, 120));
$arr = array_merge($arr, array_fill(0, $rows - (count($arr) % $rows), null));
$cols = ceil(count($arr) / $rows);
$render = array();
echo '<table>' . "\n";
foreach ($arr as $i => $value) {
$render[$i % $rows][] = $value;
if (count($render[$i % $rows]) == $cols) {
echo ' <tr>' . "\n" . ' <td>' . implode('</td>' . "\n" . ' <td>', $render[$i % $rows]) . '</td>' . "\n" . ' </tr>' . "\n";
}
}
echo '</table>' . "\n";
?>

Categories