Welcome Guest, Not a member yet? Register   Sign In
Model & Controller variable collision?
#1

[eluser]FrankieShakes[/eluser]
Sorry for the confusing title... But I'm not sure exactly how to refer to this issue.

I'm VERY new to CI, coming from a Rails background, and am attempting to use CI as closely as possible to the MVC methodology I learned using Rails. I'm not sure whether the following is even possible (may explain why I'm getting the errors), but I thought I'd ask.

I'm attempting to do the following:

Controller:

Code:
class Registrations extends Controller{
    
    public function __construct(){
        parent::Controller();
    }

    public function submit(){

        $this->load->model('Form_model', 'form', TRUE);
        $this->form->add_participant();
        
        // instead of referring to the Email library, refers to the
        // model's "email" variable's value
        echo $this->email;
        
        // set our mail fields
        $this->email->to('[email protected]');
        $this->email->from($this->form->email, $this->form->fname);
        $this->email->subject('Hello...');
        $this->email->message('World!');
        $this->email->send();
    }

Model:

Code:
class Form_model extends Model{
    
    var $fname;
    var $email;
    var $comments;
    var $CI;
    
    public function __construct(){
        parent::Model();
        
        $this->CI =& get_instance();
    }
    
    public function add_participant()
    {

             $this->fname = $this->CI->input->post('fname');
             $this->email = $this->CI->input->post('email');
             $this->comments = $this->CI->input->post('comments');
        
        
             $query_data =     array(
                 'fname' => $this->fname,
                 'email' => $this->email,
                 'comments' => $this->comments,
             );

             if ( $this->CI->db->insert('participants', $query_data) ){
                 return true;
             } else {
                 return false;
             }
        }
    
    public function list()
    {
        $query = $this->CI->db->get('participants');
        return $query;
    }
    
}

?>

The weird issue I'm having is when I attempt call any of the Email library's methods (ie: To, From, etc.), I'm greeted with the following in the logs:

Quote:[error] PHP Fatal error: Call to a member function to() on a non-object

And when I attempt to print out the value of "$this->email" in the controller, rather than getting the CI_Email object, it outputs the email address being sent in the form (View).

I'm not sure why the two values are colliding, but I'd appreciate any insight anyone has to offer. So far CI is proving to be KICK-ASS, and I'd love to use it as best I can to the way I'm used to working with MVC.


Thanks,
-f
#2

[eluser]Rick Jolly[/eluser]
You forgot to use "form" when referencing your model's email field:
Code:
echo $this->form->email;


You also have to load the email library to use it:
Code:
$this->load->library('email');
#3

[eluser]FrankieShakes[/eluser]
[quote author="Rick Jolly" date="1186300639"]You forgot to use "form" when referencing your model's email field:
Code:
echo $this->form->email;


You also have to load the email library to use it:
Code:
$this->load->library('email');
[/quote]

Hey Rick,

That line was a just a sample to show that I don't even need to access my "form" model... for some reason, the controller's reference to "email" (which should be the Email library) is being overwritten by the Form model's value (actual email address).

I forgot to mention, I have the Email library being auto loaded.
#4

[eluser]coolfactor[/eluser]
I believe the collision is happening because loading a model automatically makes available any libraries that were loaded previously. This is so that you can use the libraries in your model functions. In this case, the Form_model is getting $this->email set to the Email library, but then that is being overridden, which is a reference back to $this->email in the controller.

You could solve this by using a $this->data array in your model instead.

Code:
var $data = array();
...
$this->data['email'] = $this->CI->input->post('email');
#5

[eluser]coolfactor[/eluser]
This is yet another reason I'm wary of the Model framework in CI. If I want a library available in my model, I'll access it through the controller instance, where it's been loaded. I don't want/need a local reference to it in the model instance.

Code:
$CI =& get_instance();
// access Email library:
$CI->email->send();
#6

[eluser]FrankieShakes[/eluser]
[quote author="coolfactor" date="1186306681"]This is yet another reason I'm wary of the Model framework in CI. If I want a library available in my model, I'll access it through the controller instance, where it's been loaded. I don't want/need a local reference to it in the model instance.

Code:
$CI =& get_instance();
// access Email library:
$CI->email->send();
[/quote]

coolfactor,

I agree entirely with you. My assumptions were that setting $this->email in the Model would not affect the controller's reference to the Email library; which is why I was getting an instance to the controller through "$this->CI =& get_instance();".

Is my only way around it using the data array as you suggested? It seems a little hackish (no offence to you by any means), but I don't know whether that's the only way around it, or whether there's another way to deal with the collision issue.
#7

[eluser]Phil Sturgeon[/eluser]
Its generally much easier to yse $data arrays. With CI you use them all over the place for database active record, validation and passing to the template, so its generally alot easier that way.

Note you might also have a problem using list() in your model. Took me ages to work out why my it kept saying "undefined object/function" and its because you are using a name thats already assosiated with something else.
#8

[eluser]FrankieShakes[/eluser]
[quote author="thepyromaniac" date="1186329226"]Its generally much easier to yse $data arrays. With CI you use them all over the place for database active record, validation and passing to the template, so its generally alot easier that way.

Note you might also have a problem using list() in your model. Took me ages to work out why my it kept saying "undefined object/function" and its because you are using a name thats already assosiated with something else.[/quote]

pyromaniac,

I see your point about using the data arrays.. I guess it may be the only workaround to the problem? I just find it odd that there would be a collision when assigning a value to the model's data.

I'm guessing the problem with using a method named "list" is because of PHP's built-in "list()" method? Is it safe to assume that controller/model method names cannot use any names used by PHP? My thoughts were that as long as you didn't use any of the names mentioned in the "Reserved Function Names" section of the user guide, everything would be cool. Is that not the case? I'm running PHP 5.
#9

[eluser]coolfactor[/eluser]
Yes, once again, CodeIgniter automatically links loaded libraries into a model when you load it, so you need to create a new "namespace" to store your model data to avoid any conflicts. Using a $data array creates that separate namespace.

Personally, I hope that the auto-loading of libraries into models is dropped in a future version, except maybe for the Database library, which makes sense to have in the model instance.
#10

[eluser]FrankieShakes[/eluser]
coolfactor,

I was hoping I'd be able to workaround the namespacing issue in another way, but I guess using a $data array within the model will be the only way around this.

Thanks for the tip.




Theme © iAndrew 2016 - Forum software by © MyBB