2

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

enter image description here

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>';
}
2
  • Thanks to everyone for their answers, some interesting ways around it. I'm updating my post to say what i've ended up doing. Not sure if it's a bad way for any reason but it seems the shortest and neatest. Array_chunk seemed tidy too but not really expandable, though I don't think more will be added, you never know. Commented Sep 12, 2016 at 15:36
  • cool thanks for posting this. Commented Sep 12, 2016 at 19:28

4 Answers 4

1

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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.

1 Comment

Here's some thunder, its ok we can share :-) So i guess one advantage of your method is you could easily have access to other fields if needed, like quantity, etc. because you are getting the entire row.
0

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.

Comments

0

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>";
  }
}



?>

3 Comments

Thats interesting - but how are you going to get that to the View?
You already set the arrays and passed them to the view. So i could be wrong but i think that you want to check if they are empty or not in the view.
you are right, I have used isset() instead of empty() for array in view.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.