EllisLab text mark
Advanced Search
     
Loading a model from inside a view - is there a better way?
Posted: 05 September 2007 01:54 PM   [ Ignore ]
Joined: 2007-06-04
16 posts

It’s not really in the spirit of the MVC framework, but I can’t think of a better way to do this…

I have a controller method which loads a view for a generic new account setup:

function createAccount() {
   $this
->load->view('create_account');
One of things the user will be prompted for is the state where they reside. The list of states is in a MySQL lookup table. State’s probably won’t change anytime soon, but this is just an example. I would like my VIEW that loads a State MODEL and calls a method that displays an HTML list (dropdown menu) of states i.e. I would rather have
function createAccount() {
   $this
->load->view('create_account');
in my CONTROLLER than
function createAccount() {
   $this
->load->model('State');
   
$data['stateDropDown'$this->State->generateStateListDropDown();
   
$this->load->model('Country');
   
$data['countryDropDown'$this->Country->generateStateListDropDown();
   
$this->load->view('create_account'$data);

This is desirable for me because it makes the Controller cleaner, and I would have to repeat the steps involved in generating the dropdowns every time I wanted to use it.

When I try to load a model from within a view, I get the following error:

A PHP Error was encountered

Severity
Notice
Message
Undefined propertyCI_Loader::$State
Filename
views/stateList.php
Line Number
4

Fatal error
Call to a member function generateStateDropDown() on a non-object in /home/lee/Development/CodeIgniter_1.5.4/system/application/views/stateList.php on line 4 

Can someone suggest a cleaner implementation?

Cheers,
  Lee

 
Posted: 05 September 2007 01:58 PM   [ Ignore ]   [ # 1 ]   [ Rating: 0 ]
Avatar
Joined: 2006-06-23
370 posts

I believe you need to use them lowercased.

$this->state->generateStateListDropDown(); 
 Signature 

Mac OS X 10.8, Apache 2.x, NGiNX, PHP 5.4.x, CodeIgniter 1.7.2/2.1.3

 
Posted: 05 September 2007 02:07 PM   [ Ignore ]   [ # 2 ]   [ Rating: 0 ]
Joined: 2007-06-04
16 posts
coolfactor - 05 September 2007 05:58 PM

I believe you need to use them lowercased.

$this->state->generateStateListDropDown(); 

Thanks, but that was really just pseudocode. The same error appears regardless of the case.

 
Posted: 05 September 2007 02:13 PM   [ Ignore ]   [ # 3 ]   [ Rating: 0 ]
Avatar
Joined: 2006-06-23
370 posts

Really important that you provide _real_ code examples, or it misleads us and we can’t help you.

I can’t see what else could be wrong.

 Signature 

Mac OS X 10.8, Apache 2.x, NGiNX, PHP 5.4.x, CodeIgniter 1.7.2/2.1.3

 
Posted: 05 September 2007 02:27 PM   [ Ignore ]   [ # 4 ]   [ Rating: 0 ]
Joined: 2007-06-04
16 posts
coolfactor - 05 September 2007 06:13 PM

Really important that you provide _real_ code examples, or it misleads us and we can’t help you.

I can’t see what else could be wrong.

Oh, so it’s an error in my code? I was thinking that for some reason CI might not let me load models within views. OK here are two scenarios (with real code). My model looks exactly the same for both examples:

<?php
    
class State extends Model {
        
        
function Model_state() {
            parent
::Model();    
        
}
        
        
function generateStateDropDown() {
            
echo "TEST!";
        
}
    }
?> 

Scenario 1: The model is loaded within the view. Here’s my view:

<?php
    
echo "@ Beginning of view!<br/>";
    
//$this->load->model('State');
    //$this->state->generateStateDropDown();
    
echo "@ End of view!<br/>";
?> 
and here’ my controller method:
function createAccount() {
        $this
->load->view('create_account');
        
$this->load->model('State');
        
$this->state->generateStateDropDown();
    

This works! And prints out

Test
@ Beginning of view!
@ End of view!

Scenario 2: I comment out the loading of the model in the controller, and make the view load the model. Here’s my view:

<?php
    
echo "@ Beginning of view!<br/>";
    
$this->load->model('State');
    
$this->state->generateStateDropDown();
    echo 
"@ End of view!<br/>";
?> 
and here’s my controller method:
function createAccount() {
        $this
->load->view('create_account');
        
//$this->load->model('State');
        //$this->state->generateStateDropDown();
    

This doesn’t work and prints out

   
@ Beginning of view!
A PHP Error was encountered

Severity: Notice
Message: Undefined property: CI_Loader::$state
Filename: views/stateList.php
Line Number: 4

Fatal error: Call to a member function generateStateDropDown() on a non-object in /home/lee/Development/CodeIgniter_1.5.4/system/application/views/stateList.php on line 4

 
Posted: 05 September 2007 02:35 PM   [ Ignore ]   [ # 5 ]   [ Rating: 0 ]
Avatar
Joined: 2006-06-23
370 posts

Your Scenario #1 was the correct way to do this. You don’t want to load models in the view, as you suspected.

 Signature 

Mac OS X 10.8, Apache 2.x, NGiNX, PHP 5.4.x, CodeIgniter 1.7.2/2.1.3

 
Posted: 05 September 2007 03:12 PM   [ Ignore ]   [ # 6 ]   [ Rating: 0 ]
Joined: 2007-06-04
16 posts

Yes, but that’s just means I have to repeat a lot of code in controllers any time I want to do something as simple as generate some code to produce a dropdown list with data coming from a database.

 
Posted: 05 September 2007 03:23 PM   [ Ignore ]   [ # 7 ]   [ Rating: 0 ]
Avatar
Joined: 2006-06-23
370 posts
LeePR - 05 September 2007 07:12 PM

Yes, but that’s just means I have to repeat a lot of code in controllers any time I want to do something as simple as generate some code to produce a dropdown list with data coming from a database.

No, it all depends on how you design your code.

Option #1 - auto-load models

Option #2 - load models in the constructor, making them available across the entire controller.

Option #3 - create a wrapper library that does repetitive work for you

 Signature 

Mac OS X 10.8, Apache 2.x, NGiNX, PHP 5.4.x, CodeIgniter 1.7.2/2.1.3

 
Posted: 06 September 2007 01:59 PM   [ Ignore ]   [ # 8 ]   [ Rating: 0 ]
Joined: 2007-06-04
16 posts

Thanks for your replies. I’m just going to create some libraries (StateCollection, CountryCollection, etc).