Welcome Guest, Not a member yet? Register   Sign In
Are view files allowed to directly obtain data from a model?
#1

[eluser]Mark Skilbeck[/eluser]
In the essence of MVC architecture, I was wondering if a view is 'allowed' to directly interact with a model to retrieve data from said model, without going through the controller.
#2

[eluser]rakesh[/eluser]
why not!!
#3

[eluser]slowgary[/eluser]
There's nothing programmatic that would stop you from doing so but no, it isn't in the true spirit of MVC. They probably should call it MCV, because the M and the V shouldn't touch eachother Wink

It's not going to kill anything if you needed to do it that way. Remember: this framework, as well as MVC principles, are only here to make things easier. If you need to break the rules to make things easier than just do it. The downside is, in the long run it will probably make things harder when you need to alter your app, but your view relies specifically on your model.

You can always retrieve the output of a view if you need to do further processing, like so:

Code:
$markup = $this->load->view('my_view', $data, true);  //3rd parameter returns view to you

Then your controller can do additional processing.

What is it you're trying to do? Maybe someone can recommend a better alternative for you than accessing the model from the view.
#4

[eluser]mglinski[/eluser]
Globaly loading models in the config/autoload.php file exposes them to all view files in the $this scope.
-Matt
#5

[eluser]xwero[/eluser]
I'm all for making the view as dumb as possible but loading the model in a view is not such a bad idea as it allows you to have variables that are not cached by the loader library but then the way the model is loaded has to be flexible.
Code:
function get_data($model,$method)
{
   if (file_exists(APPPATH.'models/'.$model.EXT))
   {
      $CI =& get_instance();
      $temp_arr = explode('/',$model);
      $ci_model = end($temp_arr);

      if( ! isset($CI->$ci_model))
      {
          $CI->load->model($model,'',TRUE);
      }
      
      if(method_exists($CI->$ci_model,$method) === FALSE)
      {
         show_error('Unable to call the method you have specified: '.$method);
      }

      return $CI->$ci_model->$method();        
   }
}
If you feel uncomfortable loading the model in the view you can add the function with the name data to the extended loader class and change following line
Code:
return $CI->$ci_model->$method();
to
Code:
$CI->load->vars($CI->$ci_model->$method());
And then
Code:
$this->load->model('some_model');
$this->load->view('my_view',$this->some_model->some_method());
can be written as
Code:
$this->load->data('some_model','some_method');
$this->load->view('my_view');
#6

[eluser]Mark Skilbeck[/eluser]
Cheers for the info, everyone.

[quote author="slowgary" date="1238276463"]There's nothing programmatic that would stop you from doing so but no, it isn't in the true spirit of MVC. They probably should call it MCV, because the M and the V shouldn't touch eachother Wink

It's not going to kill anything if you needed to do it that way. Remember: this framework, as well as MVC principles, are only here to make things easier. If you need to break the rules to make things easier than just do it. The downside is, in the long run it will probably make things harder when you need to alter your app, but your view relies specifically on your model.

You can always retrieve the output of a view if you need to do further processing, like so:

Code:
$markup = $this->load->view('my_view', $data, true);  //3rd parameter returns view to you

Then your controller can do additional processing.

What is it you're trying to do? Maybe someone can recommend a better alternative for you than accessing the model from the view.[/quote]

Ok, gary. Here's the scoop. In my database I have the tables 'projects' and 'project_changelogs'. I want to display, in a view, the projects and their changelogs in list view.
Code:
- project 1
   - project 1, changelog 1
   - project 1, changelog 2

I have a couple of methods in a model that I can use to handle the retrieval of all changelogs and all projects, and I use them in the controller to pass all this data to the view.

Code:
$vars['projects']            = $this->db->get_all_projects( );
$vars['projects_changelogs'] = $this->db->get_all_changelogs( );

However, I soon realised that my view would get congested with more PHP logic than I'd like to use - having to loop through each array, grabbing the relevant data from each, as compared to if I could just call the model from my view, passing the project name (retrieved from $projects->result)) for use as a WHERE clause.

Does that make sense, or am I going about this the wrong way?

Cheers, everyone.

- Mark.
#7

[eluser]TheFuzzy0ne[/eluser]
Looks good. You can do it the way you have, but personally, I would have my model return both in a single array:
Code:
array(
    'project 1' => array(
        'change log 1',
        'change log 2'
    ),
    'project 2' => array(
        'change log 1',
        'change log 2',
        'change log 3'
    # ...And so on...
    ));

I think you'll find that easier to process within your view.

Shouldn't your signature read "RTFUG"? Tongue
#8

[eluser]slowgary[/eluser]
I don't see how calling the model from the view would remove any of the PHP logic. You'd still have to loop through your data for formatting. I've been working on a CMS that has a similar structure where there is 1 view per page, yet each page may have an unlimited number of nested lists for navigation (multiple navigations per page such as 'main_menu', 'side_menu', 'footer_menu'.

What I did was to create a view called menu_handler, then I did something like this in my controller:

Code:
foreach($menus as $menu)
{
     $temp['menu_name'] = $menu;
     $data[$menu] = $this->load->view('menu_handler', $temp, TRUE); //process markup for each menu
}

$this->load->view('page_view', $data);  //output page

By passing TRUE as the last parameter to the view() function, the view will return the markup to you instead of outputting to the page. This way you can create sub views to do extra processing work without convuluting your main view. In my situation, I actually HAD to do something like this as I need my final view to be like a template for the user, and I can't count on a user to copy and paste a chunk of code whenever they need to place a menu. I don't put ANY logic in my final view.
#9

[eluser]Mark Skilbeck[/eluser]
[quote author="TheFuzzy0ne" date="1238450761"]Looks good. You can do it the way you have, but personally, I would have my model return both in a single array:
Code:
array(
    'project 1' => array(
        'change log 1',
        'change log 2'
    ),
    'project 2' => array(
        'change log 1',
        'change log 2',
        'change log 3'
    # ...And so on...
    ));

I think you'll find that easier to process within your view.[/quote]

Ah, that clears it up. How would you name that method? - I'm terrible at naming.

Quote:Shouldn't your signature read "RTFUG"? Tongue

Fixed. Wink
#10

[eluser]Mark Skilbeck[/eluser]
[quote author="slowgary" date="1238451287"]I don't see how calling the model from the view would remove any of the PHP logic. You'd still have to loop through your data for formatting. I've been working on a CMS that has a similar structure where there is 1 view per page, yet each page may have an unlimited number of nested lists for navigation (multiple navigations per page such as 'main_menu', 'side_menu', 'footer_menu'.

What I did was to create a view called menu_handler, then I did something like this:

Code:
foreach($menus as $menu)
{
     $temp['menu_name'] = $menu;
     $data[$menu] = $this->load->view('menu_handler', $temp, TRUE);
}

$this->load->view('page_view', $data);

By passing TRUE as the last parameter to the view() function, the view will return the markup to you instead of outputting to the page. This way you can create sub views to do extra processing work without convuluting your main view. In my situation, I actually HAD to do something like this as I need my final view to be like a template for the user, and I can't count on a user to copy and paste a chunk of code whenever they need to place a menu. Make sense?[/quote]

Ok, I see your point. I don't have time to explain how I was doing it (which was a lot more congested than the way I proposed (calling the model)). Thanks for the advice.

- Mark.




Theme © iAndrew 2016 - Forum software by © MyBB