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>";
}
}
?>
Related
I'm becoming a little frustrated with my array results. Ideally, I am creating a form maker module within my application and I am working with two different arrays to establish my database columns and excel columns. Essentially, I am using the results provided by the arrays to write directly to a php file (Excel reader file). In order to establish a difference in Excel Workbooks, I am putting forth an identifier "page2","page3" and so on within the "excel_rows" array.
//my arrays
$table_columns = array('field1','field2','field3','field4','field5'); //fields
$excel_rows = array('c1','c2','page2','c3','c4','page3','c5'); //excel columns
From here.. I go on to try to filter the array keys..
foreach(array_keys($excel_rows) as $key){
$page = array_search(strpos(trim($excel_rows[$key]),'page'),$excel_rows);
if(strpos(trim($excel_rows[$key]),'page') !== false){
$excel_row .= '$objTpl->setActiveSheetIndex('.(str_replace('page','',trim($excel_rows[$key])) -1).');<br/>'.PHP_EOL;
$table_columns[$key] = 0;
}
else {
$excel_row .= '$objTpl->getActiveSheet()->setCellValue(\''.trim($excel_rows[$key]).'\',$row[\''.trim($table_columns[$key]).'\']);<br/>'.PHP_EOL;
}
}
print $excel_row;
The result should echo out the following:
$objTpl->getActiveSheet()->setCellValue('c1', $row['field1']);
$objTpl->getActiveSheet()->setCellValue('c2', $row['field2']);
$objTpl->setActiveSheetIndex(1);<br/>
$objTpl->getActiveSheet()->setCellValue('c3', $row['field4']);
$objTpl->getActiveSheet()->setCellValue('c4', $row['field5']);
$objTpl->setActiveSheetIndex(2);
$objTpl->getActiveSheet()->setCellValue('c5', $row['']);
As one can see, I am missing 'field3' from my result and 'cs' produces and empty row rather than "field5".
I'm assuming something like array_compare or array_combine is the solution - I'm just not able to put it together.
Everything works lovely with module pardoning the array code above. Any help with this would be sincerely appreciated!
-Regards.
How it currently is I'd say you need to set an integer +1 whenever you create a new page and then subtract that integer from the key so you can get the right field.
$subkey = 0;
foreach(array_keys($excel_rows) as $key){
$fieldkey = $key - $subkey;
$page = array_search(strpos(trim($excel_rows[$key]),'page'),$excel_rows);
if(strpos(trim($excel_rows[$key]),'page') !== false){
$excel_row .= '$objTpl->setActiveSheetIndex('.(str_replace('page','',trim($excel_rows[$key])) -1).');<br/>'.PHP_EOL;
//$table_columns[$key] = 0; I'm not sure what this is supposed to do
$subkey++;
}
else {
$excel_row .= '$objTpl->getActiveSheet()->setCellValue(\''.trim($excel_rows[$key]).'\',$row[\''.trim($table_columns[$fieldkey]).'\']);<br/>'.PHP_EOL;
}
}
print $excel_row;
In my PHP application. I am taking value from user and all these user values are stored in Array. And just for validation. I am comparing user input value with my array. :-
<?php
// Current Code
$masterArray = array(......); // ..... represents some 60-100 different values.
foreach($_POST as $key => $value) {
if(in_array($value, $masterArray)) {
$insertQuery = $mysqli->query("INSERTION stuff or Updating Stuff");
} else {
echo "Are you tampering html-form-data ?";
}
}
?>
But this is so worthless code, as it takes quite good time in updating or insertion.
Is there any better function that is way faster to check if value in slave array exists in master array ?
From Slave Array i Mean => List / Array of User Input value.
From Master Array i mean => List of my array value stored in page.
Thanks
I think i got the better option with array_diff.
Please let me know if i am doing anything wrong in below before i put this code in production page:- Thanks a lot for your efforts #J.David Smith & #grossvogel
<?php
$masterArray = array(.......); // My Master Array List
$result = array_diff($_POST['checkBox'], $masterArray);
if(count($result) > 0) {
// If they are trying to do some tampering , let them submit all again.
echo 'Something is not Right';
} else {
// If Person is genuine, no waiting just insert them all
$total = count($_POST['checkBox']);
$insertQuery = "INSERT into notes(user,quote) values ";
for($i=0;$i<=$total; $i++) {
array_push($values, "('someuser','".$mysqli->real_escape_string($_POST['checkBox'][$i])."')");
}
$finalQuery = $mysqli->query($insertQuery.implode(',', $values));
}
?>
Is my Code Better , I am testing it in localhost i don't see much of difference, I just want to know expert views if I am messing arround with something ? before i put this code in production page.
Update : This looks pretty better and faster than code in question.
Thanks
The only other way to do this is to use an associative array with your values as keys (well, you could custom-implement another storage container specifically for this, but that'd be overkill imo). Then, you can check with isset. For example:
$masterArray = array(....); // same thing, but with values as keys instead of values
foreach($_POST as $key => $value) {
if(isset($masterArray[$value])) {
// do stuff
} else {
// do stuff
}
}
I'm kind of curious what the point of doing this is anyway, especially given the statement printed by your echo call. There may be an even better way to accomplish your goal than this.
EDIT: Another method suggested by grossvogel: loop over $masterArray instead of $_POST. If you expect $_POST to be a large set of data consistently (ie most of the time people will select 50+ items), this could be faster. Hashing is already very fast, so you'll have to benchmark it on your code in order to make a decision.
$masterArray = array(...); // either style of definition will work; i'll use yours for simplicity
foreach($masterArray as $value) {
if(isset($_POST[$value])) {
// do stuff
}
}
I have a controller function in CodeIgniter that looks like this:
$perm = $this->job_m->getIdByGroup();
foreach($perm as $pe=>$p)
{
$pId = $p['id'];
$result = $this->job_m->getDatapermission($pId);
}
$data['permission'] = $result;
What I need to do is list the data in the result in the view, but I get only the last value while using this method. How can I pass all the results to the view?
Store it in an array. Like this:
foreach($perm as $pe=>$p){
$result[] = $this->job_m->getDatapermission($p['id']);
}
Because $result is not an array...
try this:
$result=array();
foreach($perm as $pe=>$p)
{
$pId = $p['id'];
$result[] = $this->job_m->getDatapermission($pId);
}
$data['permission'] = $result;
Note:
My answer uses a counter to enable the display of a single group result when needed.
Guessing from your need to loop and display the value of $result, possibly, it is an array or object returned by $query->result(). Things could be a bit complex.
Example: if $perm is an array of 5 items( or groups), the counter assigns keys 1 - 5 instead of 0 - 4 as would [] which could be misleading. Using the first view example, you could choose to display a single group value if you wants by passing it via a url segment. Making the code more flexible and reusable. E.g. You want to show just returns for group 2, in my example, $result[2] would do just that else next code runs. See my comments in the code.
$perm = $this->job_m->getIdByGroup();
$counter = 1;
foreach($perm as $pe=>$p)
{
$pId = $p['id'];
$result[$counter] = $this->job_m->getDatapermission($pId);
$counter++;
}
$data['permission'] = $result;
As mentioned above Note:
I Added a Counter or Key so you target specific level. If the groups are:
Men, Women, Boys, Girls, Children; you'd know women is group two(2) If you desire to display values for just that group, you don't need to rewrite the code below. Just pass the group key would be as easy as telling it by their sequence. To display all the loop without restrictions, use the second view example. To use both, use an if statement for that.
###To access it you could target a specific level like
if(isset($permission)){
foreach($permission[2] as $key => $value){
echo $value->columnname;
}
###To get all results:
foreach($permission as $array){
foreach($array as $key => $value){
echo $value->columnname;
}
}
}
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?
Thanks to the many folks who help us out here on Stackoverflow. You all are awesome! Now to the question. I've got an array for the following values: "duck", "chicken","egg", "pork", "steak", "beef", "fish", "shrimp", "deer", and "lamb."
I've gotten the list to display in Alphabetical order. This is a dynamic array, so it may not always have all these values or be in that order. I'd like to have "Steak" always appear first with "Top Choice" next to it, while keeping the rest in alphabetical order with "Available for Order" next to them.
Here's what I've got thus far with $meat_items as the array:
foreach($meat_items as $meat_item)
echo $meat_item . ' Available for Order <br>';
I should clarify: Steak may NOT always be a part of the array.
Since you always want steak to appear first, hard code it:
if (in_array("steak", $meat_items)) {
`echo "Steak: Top Choice";`
}
Sort your array alphabetically:
sort($meat_items);
Then loop through your array, echoing all items except the steak:
foreach ($meat_items as $meat_item) {
if ( "steak" != $meat_item ) {
echo $meat_item . ' Available for Order<br />';
}
}
if (!empty($meat_items['steak']))
{
echo 'Steak Top Choice <br >';
unset($meat_items['steak']);
}
sort($meat_items);
foreach($meat_items as $meat_item)
echo $meat_item . ' Available for Order <br>';
A more general purpose way to do this is to tell PHP how to sort the items, by defining a sorting "comparison" that prefers the "top choices", and then passing it to usort.
I don't really know PHP, but something like:
function prefer_top($a, $b) {
/* We can modify this array to specify whatever the top choices are. */
$top_choices = array('Steak');
/* If one of the two things we're comparing is a top choice and the other isn't,
then it comes first automatically. Otherwise, we sort them alphabetically. */
$a_top = in_array($a, $top_choices);
$b_top = in_array($b, $top_choices);
if ($a_top && !$b_top) { return -1; }
if ($b_top && !$a_top) { return 1; }
if ($a == $b) { return 0; }
return ($a < $b) ? -1 : 1;
}
usort($meat_items, "prefer_top");
// and then output them all in order as before.