4

I am new to MVC, I am porting a project written in non-MVC style to MVC, but I am stuck on a problem where it is necessary to call Model function in View.

Scenario:

Table1 - Products:
contains product_id, product_name etc. and for each product there can be multiple versions.

Table2 - Versions:
contains version_id, version_name, ... , product_id etc.

Now in the View I am displaying products and under each product heading I have to display version list of that product, in non-MVC style it was pretty simple, I can use the following code snippet in View:

foreach ($product as $row) 
{
    echo $row['product_name'];
    if ($main->getVersionList($vresult,$row["product_id"]))
    {
        foreach ($vresult as $vrow)
        {
          echo $vrow['version_name'];
        }
    }
}

Now, I can pass Product array from controller to view but what about each Version array which needs to be generated corresponding to each product?

Update:

This is my final working solution (used a map), in controller:

        $this->load->model ( 'product_mod' );
        $data ['products'] = $this->product_mod->getProductList ();
        $data ['versions'] = array ();
        foreach ( $data ['products'] as $product )
        {
            $data ['versions'] [$product['product_id']] =   $this->product_mod->getVersionList ( $product['product_id'] );
        }
Marco Demaio
  • 33,578
  • 33
  • 128
  • 159
adnan kamili
  • 8,967
  • 7
  • 65
  • 125
  • Just updated the answer to fit your needs. – Hashem Qolami Feb 09 '14 at 19:03
  • Thanks for posting your solution -- arrays can be so confusing to figure out -- its funny how simple it usually is to implement :-) – cartalot Feb 09 '14 at 19:52
  • @cartalot Runnig SQL queries within loops causes overhead and doesn't make any sense while you're using **[RDBMS](http://en.wikipedia.org/wiki/Relational_database_management_system)**. You could `JOIN` the tables to fetch the related data, as I suggested in [my answer](http://stackoverflow.com/questions/21662859/calling-model-function-in-view-codeigniter/21663343#21663343). – Hashem Qolami Feb 10 '14 at 12:52

3 Answers3

8

MVC or not to MVC

The first thing I should note is that It is impossible to write classical MVC in PHP. In fact the MVC-like PHP frameworks such as CodeIgniter or Yii implements sort of MVP in which:

  • view is passive and unaware of model
  • presenter (controller) changes state of model, reads information and passes it to view

Credits to tereško

CodeIgniter Approach

However, particularly in CodeIgniter, you have 3 steps:

  • Create a Model to query through the database and return the data (as an array or object)
  • Create a Controller to load and fetch the result from the Model (a method of the Model), and pass the returned data to the view
  • Create a View and use PHP loops to echo the result out, build the HTML.

Getting all together

Considering the above approach, you need to fetch the result from the database in your Model:

application/models/product.php

class Product extends CI_Model
{
    public function get_product($product_id)
    {
        $this->db->select('*')->from('products');
        $this->db->where('product_id', $product_id);
        $this->db->join('versions', 'versions.product_id = products.product_id');
        $query=$this->db->get();
        return $query->first_row('array');
    }
}

Then fetch and pass the result within the Controller:

application/controllers/products.php

class Products extends CI_Controller
{
    public function view($product_id)
    {
        $this->load->model('product');
        // Fetch the result from the database
        $data['product'] = $this->product->get_product($product_id);
        // Pass the result to the view
        $this->load->view('product_view', $data);
    }
}

Finally, use the returned data in the view, to generate the list:

application/views/product_view.php

// Use $product to display the product.
print_r($product);
Community
  • 1
  • 1
Hashem Qolami
  • 97,268
  • 26
  • 150
  • 164
  • Anyone who downvoted this answer, consider to leave a comment in you found this irrelevant or useless – Hashem Qolami Feb 09 '14 at 19:56
  • It doesn't seem to defer much from using foreach loop solution above because I have to call the above function for each product id, as using following where condition in above function: $this->db->where('username', $username); results in a null array. – adnan kamili Feb 10 '14 at 19:13
  • @adnankamili I assumed you want to display **only** one product. in order to display the whole products, you should remove the *WHERE* clause and use `$query->result_array()` instead. And it improves the performance, you could use the CI profiler to compare the benchmarks. Here you can check the functionality of [SQL JOIN](http://www.w3schools.com/sql/trysql.asp?filename=trysql_select_join). – Hashem Qolami Feb 10 '14 at 21:17
  • AFAIK *"view is passive and unaware of model"* is not true in CodeIngniter 3.1.9. If you load the model in the controller, you can use it from within the view. E.g. in the **controller** you call `$this->load->model('mymodel');` then in **view** (loaded by such controller) you can call `$this->mymodel->someMethod();` – Marco Demaio Dec 08 '18 at 23:54
2

You should do mysql query in your model, for example products_model (don't forget to load it)

Example Query : This is just select * from products

public function All_Products()
{
$this->db->select('');
$result = $this->db->get('products')->result_array();
return $result;
}

So as I see , you are foreach guy like me, rather than using mass queries.

In your controller you could load $products my your model.

$products = $this->products_model->All_Products();

My solution is creating a new array then putting new values in it.Also you need to getVersionList function in your model.

$newArray = array ();
foreach ( $products as $values ) {
$version = $this->products_model->getVersionList($values['product_id']);
$tmp = array (
'product_id' => $values ['product_id'], 
'product_name' => $values ['product_name'], 
'version' => $version
);
array_push ( $newArray, $tmp );
}

So add your new array to $data you could have them in your view file.

$data ['products'] = $newArray;

Sorry I didnt figure out all your queries but I think its better to teach how to catch fish than giving a fish.

Mehmet Uyarovic
  • 304
  • 2
  • 9
2

Using the below code you can call the model's method in the view file. It's worked for me and is so simple also.

$CI =& get_instance();
$CI->model_name->method_name();
Devendra Rajput
  • 432
  • 7
  • 13