PHP display order for iterating through multiple arrays - php

In essence, I have 3 arrays. These are serialised, stored to the DB, un-serialised and then outputted to a page. myFirstArray, mySecondArray, & myThirdArray.
From what I gather - I need to be using a foreach loop, or a for loop with a counter, as the 3 arrays are all of (the same) unknown length. By that I mean one user may have stored 4 items into each of the 3 arrays, but another user might have stored 8 items into each of the 3 arrays.
I'm trying to get the output to look something like this:
myFirstArray[0], mySecondArray[0], myThirdArray[0]
myFirstArray[1], mySecondArray[1], myThirdArray[1]
myFirstArray[2], mySecondArray[2], myThirdArray[2]
The current code I have is as follows:
foreach ($myFirstArray as $value1){
echo $value1 . " ";
}
foreach ($mySecondArray as $value2){
echo $value2 . " ";
}
foreach ($myThirdArray as $value3){
echo $value3 . "<br>";
}
I am aware that this code is never going to output my arrays as I would like, but I'm having some difficulty with working out the logic behind what I need. I haven't rushed straight to StackOverflow to ask, but nothing else I've seen has been very helpful!

Since both arrays have the same length, I propose
$length = count($myFirstArray);
for($i = 0; $i <$length ; $i++) {
echo $myFirstArray[$i].','.$mySecondArray[$i].','.$myThirdArray[$i].'<br/>';
}
This will loop through all of your arrays at the same time :) .

Related

Php count elements inside loop not outside

I know how to count elements inside a loop, but tried and can´t find a solution. Actually, I can count the elements in loop in this way:
$i = 0;
foreach ($Contents as $item)
{
$i++;
}
echo $i;
But in my case, I have large function and I can do this, but need more time for count elements inside. I can´t put the string for showing number elements inside loop outside of the function. I must show inside loop all number of elements and show as this. Here's an example:
$i = 0;
foreach ($Contents as $item)
{
print "Number Elements it´s : $i";
print "Element ".$i."<br>";
$i++;
}
The problem here is that the phrase "number elements it´s" always repeats, because inside loop, and all time $i show me 0,1,2,3,4,5 ...... and all time the same as number of elements inside loop.
My idea and question is if it´s possible inside loop to show the number of elements and after this show the elements as this structure when executing the script:
Númber elements it´s : 12
Element 1
Element 2
Element 3
.
.
.
.......
This it´s my question. I hope you understand it all. Thanks in advance.
As mentioned in the comments, youu will need to use the count() function for that. If you insist on having it inside the loop, simply do it like this:
$i = 0;
foreach ($Contents as $item)
{
if($i == 0) {
print "Number of Elements is : " . count($Contents) . "<br><br>";
}
print "Element ".$i."<br>";
$i++;
}

MVC multi-dim array displaying in view

I can't think my way through this one. I'm still learning arrays so go easy on me. I'm using codeigniter.
I have 3 tabs (1 month, 2 month, 3 month) in my mark-up.
Each tab shows 3 price boxes (3 levels - basic=1, standard=2, featured=3).
I need to display 9 prices overall, pulled from 1 look-up:
return $this->db->get('prices')->result_array();
In the database it's like this
Should I be trying to do it from one look-up as shown in my model or should I be doing several look-ups, or should I just be managing that look-up in the controller setting vars, ready to display in the view or just doing everything in the view? And How? The only think of 3x foreach loops, where inside the loop I say:
if($prices['months']==3) echo $prices['level'].' is '.$prices['amount'].'<br>';
I'd like to know the BEST way to do this but also how to do the array from one look-up, because I think I really need to get my head around arrays properly. Thanks :)
-- EDIT to show what I've ended up using below --
In the controller, sort of inspired by array_chunk but more manual and to allow for the table to expand, is setting array keys which I read up on in php manual:
foreach ($prices as $price_row) {
$data['prices'][$price_row['months']][] = $price_row;
}
Then in the view I can just use foreach for a month:
foreach ($prices[1] as $p) {
echo level_name($p['level']).' = '.$p['amount'].'<br>';
}
i did not test this so might have made a stupid error - but basically you can foreach through each of your products - make an array - and then use that array in your view.
// in your model Note I am returning an object not an array
// and always check to make sure something got returned
if( ! $products = $this->db->get('prices')->result() )
{
return false:
}
else
{
$prices = array();
foreach($products as $product)
{
// append the months number to the word 'months' to make it clear
$month = $product->months . 'month' ;
// same with level
$level = 'level' . $product->level ;
// build the array
$prices[$month][$level] = $product->amount ;
}//foreach
return $prices ;
}//else
so then in your controller - make sure something came back from the model, assign it to data, then pass data to your view
if( ! $data['prices'] = $this->somemodelname->returnPrices() )
{
$this->showError() ;
}
else
{
$this->load->view('yourviewname', $data);
}
and then in your view you could foreach or just echo out each price if it needs to follow some layout.
echo '1 month level 1 $' . $prices['1month']['level1'] ;
and remember your best friend when doing arrays is print_r wrapped in pre tags so like
echo 'start prices <br> <pre>' ;
print_r($prices) ;
echo '</pre>' ;
opinions - its fine to build stuff in the controller and the view while you are developing and building out. but get in the habit of refactoring to your models. keep your controllers as clean and thin as possible. if your views need complicated data structures - build them in a model first. that way if something goes wrong - your controller can decide what to do. AND you don't have to check in your view if $prices is set and valid because you have already done it. this minimizes where things can go wrong.
Here's a pretty easy way to sort the db return into separate arrays and then display them. #caralot stole my thunder so I came up with this alternative.
Using your current model return $this->db->get('prices')->result_array(); and assigning it to $data.
$data = $this->db->functionName();
//You should check $data validity but I'm skipping that
$month1 = [];
$month2 = [];
$month3 = [];
foreach($data as $row)
{
if($row['months'] === '1')
{
$month1[] = $row;
}
elseif($row['months'] === '2')
{
$month2[] = $row;
}
else
{
$month3[] = $row;
}
}
echo "Month 1<br>";
foreach($month1 as $month){
echo "Level ". $month['level'].' is '.$month['amount'].'<br>';
}
echo "Month 2<br>";
foreach($month2 as $month){
echo "Level ".$month['level'].' is '.$month['amount'].'<br>';
}
echo "Month 3<br>";
foreach($month3 as $month){
echo "Level ".$month['level'].' is '.$month['amount'].'<br>';
}
If your table was less ordered than what you show it would be necessary to add a $this->db->order_by('level', 'ASC'); call to the query.
It is such a tiny dataset that you should definitely do a single lookup. Sorting the array into three arrays in your controller would make more sense as it will leave your view much cleaner, and allow you to set defaults should there be no data (say level 1 for 3 months is removed) if you need to. You are always going to need three foreach loops unless you construct the entire table in one go, setting breaks and new column headings when the level indicator changes.
There is no 'Best' way to do this, it is all case dependent on complexity of layout, future data development and your requirements. Usually though you minimize the number of queries, and keep data manipulation to a minimum within you views. So ideally you will have three arrays, one for each column, sent to your view.
In your controller,
$result = $this->db->query("SELECT * from prices");
$result=$result->result();
$tab1=array();
$tab2=array();
$tab3=array();
foreach ($result as $res) {
switch($res->months)
{
case 1: array_push($tab1, $res);
break;
case 2: array_push($tab2, $res);
break;
case 3: array_push($tab3, $res);
break;
}
}
//var_dump($tab3); //array tab1 for month1, array tab2 for month2, array tab3 for month3
$data['tab1']=$tab1;
$data['tab2']=$tab2;
$data['tab3']=$tab3;
$data['include']=$this->load->view('myview', $data);
In your view i.e myview in my case,
<?php
if(!empty($tab1))
{
echo "Tab 1"."<br>";
foreach($tab1 as $tb)
{
echo "For level ".$tb->level." price is ".$tb->amount."<br>";
}
}
if(!empty($tab2))
{
echo "Tab 2"."<br>";
foreach($tab2 as $tb)
{
echo "For level ".$tb->level." price is ".$tb->amount."<br>";
}
}
if(!empty($tab3))
{
echo "Tab 3"."<br>";
foreach($tab3 as $tb)
{
echo "For level ".$tb->level." price is ".$tb->amount."<br>";
}
}
?>

Using "array_values" with "foreach" data?

I am trying to organize an array of data to be sent in an email. I have no problem getting the data, but I am not sure how to organize it.
Foreach: Here outputs a list of questions generated by the user in the backend
$message = array();
foreach($questions['questions'] as $key => $value){
if(is_array($value) && isset($value[ 'questionlist'])){
foreach($value as $key => $subquestion){ //line 119
foreach ($subquestion as $key => $value){
$message[] = $value['a-question'];
}
}
}
}
I am trying to conjoin the data with each other, the data from the foreach and the $_POST data which is check values.
My logic for doing it this way is because one comes from the database, one is just form data (that does not need to be saved to the database it comes from the front end unlike the data from the database that is generated via backend) That said there perhaps is a better way, but I pretty much got this I am just not sure how to join the data so it looks like
<li>MYARRAYDATA - MYFORMDATA</li>
<li>MYARRAYDATA - MYFORMDATA</li>
<li>MYARRAYDATA - MYFORMDATA</li>
//The form input data '0', '1' values
$checks = $_POST['personalization_result'];
//Putting that data into array_values
$checkValues = array_values($checks);
//Then passing the array_values into 'implode' and organizing it with a list (<li>)
$checkString = '<li>'.implode('</li><li>',$checkValues).'</li>';
//Then testing with var_dump outputs a nice list of '0','1' values
var_dump ($checkString);
Trying the same method but trying to conjoin the foreach array and the check values does not work, here is an example.
//Similar to $checkValues I pass the data from the foreach into "array_values"
var_dumping this works fine.
$arrayValues = array_values($message);
//This is obvious it's the same as above it "implodes" the data nicely into a list(<li>)
$arrayString = '<li>'.implode('</li><li>',$arrayValues).'</li>';
//This var dumps the "$arrayString" nicely
var_dump ($arrayString)
Again the actual question is here, how do I conjoin each piece of data?
My Attempts: Here are my attempts for "conjoining" the data.
// This does not work well (maybe by cleaning up it can work) but it outputs 2 separate lists
var_dump ($arrayString.'_'.$checkString);
//I tried to run it inside one implode variable this is invalid arguments
$checkString = '<li>'.implode('</li><li>',$arrayValues.'_'.$checkValues).'</li>';
//Modified one implode variable this outputs see below
$checkString = '<li>'.implode('</li>'.$arrayValues.'<li>',$checkValues).'</li>';
<li>Array
1</li>
<li>Array
0</li>
<li>Array
1</li>
<li>Array
0</li>
var_dump results: Here is the var_dump result of each array, I want to combine these into one list
$_POST array
// Var dump of form $_POST DATA
var_dump ($checkString);
//Result
1 //This is generated through the $_POST method not on database
0 //This is generated through the $_POST method not on database
1 //This is generated through the $_POST method not on database
0 //This is generated through the $_POST method not on database
DATABASE array
// Var dump of datbase generated from backend
var_dump ($arrayString);
//Result
I am 1 //This is generated in the backend and is stored on a database
Hi I am 2 //This is generated in the backend and is stored on a database
civil is 3 //This is generated in the backend and is stored on a database
THIS IS FOURTA //This is generated in the backend and is stored on a database
The Goal
I am 1 - 1 //This is checked
Hi I am 2 - 0 //This is NOT checked
civil is 3 - 1 //This is checked
THIS IS FOURTA - 0 //This is NOT checked
The Answer: Thanks to #xdim222
I didn't understand it at first, because of the increment, but now I understand it all, initially it would have worked but my variables were under the foreach statement and that was causing it not to return the array.
At least in my opinion thats what it was, because when I added the variable above the foreach it worked.
I modified the answer to suit my code.
//$messages = array('test1', 'test2', 'test3', 'test4', 'test5');
//Instead of using this array I used the array generated in my foreach above.
// Instead of this $checks = array(1,0,1,0); I take the $_POST value which generates an array, you can see above.
$checkValues = array_values($checks);
$checkString = implode($checkValues);
$i=0;
foreach($messages as $msg) {
echo $msg . ' - ' . ( isset($checkString[$i])? $checkString[$i] : 0 ) . '<br>';
$i++;
}
Again thanks to #xdim222 for being patient, reading my long question, and most importantly helping me learn, by asking this question and finding a solution this stuff really sticks and is in my opinion the best way to learn (by asking). :)
To make it easier, I assign $messages and $checks directly, I have tried this code and it works. You might have different elements of your arrays, but I think you can figure it out from my code below:
$messages = array('test1', 'test2', 'test3', 'test4', 'test5');
$checks = array(1,0,1,0);
$i=0;
foreach($messages as $msg) {
echo $msg . ' - ' . ( isset($checks[$i])? $checks[$i] : 0 ) . '<br>';
$i++;
}
PS: I made a mistake in my previous answer by incrementing $i before echoing things out, array element should start by 0.
While waiting for your reply to my comment above, I'm trying to write some code here..
I assume you want to display the questions that were pulled from database and it should be displayed based on what user chose in the form. So you may use this code:
foreach($questions['questions'] as $key => $value){
if(is_array($value) && isset($value[ 'questionlist'])){
foreach($value as $key => $subquestion){ //line 119
foreach ($subquestion as $key => $value){
$message[$key] = $value['a-question'];
}
}
}
}
I added $key in $message in the code above, with an assumption that $key is the index of a question, and this index will be matched with what user chose in the form. Then we can list all the questions that a user have chosen:
foreach($checks as $check)
echo '<li>'.$check . ' - ' . $message[$check].'</li>';
Is this what you want?
Based on your update:
$i=0;
foreach($message as $msg) {
$i++;
echo '<li>'. $msg . ' - ' . ( isset($checks[$i])? $checks[$i] : 0 ) . '</li>';
}
Maybe this is what you want.
As I said, there should be a relation between the $message and $checks, otherwise the above code looks a bit weird, because how do we know that a question is selected by user? Maybe you should show how you get that $_POST['personalization_result'] in your HTML.

Create PHP array's on the fly

I am having the worst time trying to get this to work. In the following code, I am gathering data from a database query and trying to build a muti-dimensional array object that will keep totals and tally up some information in a specific way. The problem is that instead of getting a value that is incrementing as it should, the value seems to be suffering from the last value it was assigned problem. Here is the code:
$REVIEWS = array();
$USER_REVIEWS = array();
$USER_IMGREVS = array();
pseudo-code: loop here which iterates over the DB results creating
$date - which is into this function as its called for each day of month
$p1user - which is one of the users (there are 3) 'levels' of users
$hr - is the hour which is built from the transaction's timestamp
$hr = date('H', $row['P1TIMESTAMP']);
$p1user = $row['P1USER'];
$REVIEWS[$date] += 1;
$USER_REVIEWS[$date][$p1user][$hr] += 1;
$USER_IMGREVS[$date][$p1user][$hr] += $row['F5'];
print "PASS1<br/>\n";
print "Value of Total Reviews: [".$REVIEWS[$date]."]<br/>\n";
print "Value of User Reviews: [".$USER_REVIEWS[$date][$p1user][$hr]."]<br/>\n";
print "Value of Reviewed Images: [".$USER_IMGREVS[$date][$p1user][$hr]."]<br/>\n";
print "<br/><br/>\n";
So - the 'total reviews' increments by one, as it should, for each time i print this. SO far so good. The next two arrays will only print the last values they were assigned, and will not be added together like they should. Why not? I have attempted to do this another way by literally creating the arrays one by one and assigning them in whole to the array containing them - but that also does not seem to work. Any insights?
i don't know how you initilize your array, maybe this will help:
// replace this 2 lines:
$USER_REVIEWS[$date][$p1user][$hr] += 1;
$USER_IMGREVS[$date][$p1user][$hr] += $row['F5'];
// with this code:
if (!isset($USER_REVIEWS[$date]))
$USER_REVIEWS[$date] = array();
if (!isset($USER_REVIEWS[$date][$p1user]))
$USER_REVIEWS[$date][$p1user] = array();
if (!isset($USER_REVIEWS[$date][$p1user][$hr]))
$USER_REVIEWS[$date][$p1user][$hr] = 0;
$USER_REVIEWS[$date][$p1user][$hr] += 1;
if (!isset($USER_IMGREVS[$date]))
$USER_IMGREVS[$date] = array();
if (!isset($USER_IMGREVS[$date][$p1user]))
$USER_IMGREVS[$date][$p1user] = array();
if (!isset($USER_IMGREVS[$date][$p1user][$hr]))
$USER_IMGREVS[$date][$p1user][$hr] = 0;
$USER_IMGREVS[$date][$p1user][$hr] += $row['F5'];
Sir, I dont understand very well why your coed is not working, but in my first test, I would change these lines:
$count = 1;
$USER_REVIEWS[$count][$p1user][$hr] += 1;
$USER_IMGREVS[$count][$p1user][$hr] += $row['F5'];
$count++;
Please, check if this code helps you anyway.
Your print statements for those values rely on the value of $p1user:
print "Value of User Reviews: [".$USER_REVIEWS[$date][$p1user][$hr]."]<br/>\n";
print "Value of Reviewed Images: [".$USER_IMGREVS[$date][$p1user][$hr]."]<br/>\n";
If you want to print it for all users you should loop over all possible users rather than just using $p1user. Either that or add them up if you want their sum.
Edit: Something that was bugging me was your data structure. It doesn't seem to represent your data very well. In your loop why don't you build up useful information that you store at the base of the review array?

How can I find out how many times a foreach construct loops in PHP, without using a "counter" variable?

If I have a foreach construct, like this one:
foreach ($items as $item) {
echo $item . "<br />";
}
I know I can keep track of how many times the construct loops by using a counter variable, like this:
$counter = 0;
$foreach ($items as $item) {
echo $item.' is item #'.$counter. "<br />";
$counter++;
}
But is it possible to do the above without using a "counter" variable?
That is, is it possible to know the iteration count within the foreach loop, without needing a "counter" variable?
Note: I'm totally okay with using counters in my loops, but I'm just curious to see if there is a provision for this built directly into PHP... It's like the awesome foreach construct that simplified certain operations which are clunkier when doing the same thing using a for construct.
No it's not possible unless your $items is an array having contiguous indexes (keys) starting with the 0 key.
If it have contiguous indexes do:
foreach ($items as $k => $v)
{
echo $k, ' = ', $v, '<br />', PHP_EOL;
}
But as others have stated, there is nothing wrong using a counter variable.
There's no easier way - that's kinda what count variables are for.
I'm assuming that you want to know the current count during the loop. If you just need to know it after, use count($items) as others have suggested.
You could tell how many time it WILL loop or SHOULD have looped by doing a
$loops = count($items);
However that will only work if your code does not skip an iteration in any way.
foreach loops N times, where N is just the size of the array. So you can use count($items) to know it.
EDIT
Of course, as noticed by Bulk, your loop should not break (or maybe continue, but I would count a continue as a loop, though shorter...)

Categories