• 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Model can’t load or use libraries or other models from the constructor

#1
[eluser]enrico.simonetti[/eluser]
Hi guys,
I’ve found this unexpected behavior in CI 1.7.2.

I have a model and from his constructor I need to load something (it can be a library or another model).

It will fail.

This is affected even when autoloading a model/library.


The constructor can either be '__construct' or the className method.

If I execute from inside the constructor something like:
$this->load->model('test_model');
$this->test_model->test('a','b','c');

It will fail with:
Fatal error: Call to a member function model() on a non-object...

If instead I write the same code inside any other method it works fine.
The aim is to load some libraries/models for the whole class, not just for a method.

A workaround can be to get an instance of CI and load the library/model with his aid.

Eg:
$this->ci =& get_instance();
$this->ci->load->model('test_model');
$this->ci->test_model->test('a','b','c');


Did you guys experience this issue yourself?

Thanks

#2
[eluser]Colin Williams[/eluser]
That's because in a model class, $this references the current class, and all of those libraries and models are assigned to the controller class, which can be obtained with the get_instance() function.

CI does copy over some of the controllers references, but only when the model is loaded, not every time a library or other model is loaded. Think about two distinct objects, a Model and a Controller, and keep in mind who has what.

#3
[eluser]enrico.simonetti[/eluser]
This doesn't still explain why, if I load model A and B from the controller, and from inside model A, i use model B, it works fine from any other method that is not the constructor.

Is this expected?

So I can't load anything from the model, and I can use the loaded models from the methods that are not the constructor?

Thanks

#4
[eluser]Colin Williams[/eluser]
It is very expected. Two distinct steps.

A. Model is instantiated (this is when the constructor runs)
B. References are copied from the controller to the instantiated model.

Quote:So I can’t load anything from the model

You can, but you have to use the controller to do it.

Code:
$ci =& get_instance();
$ci->load->library('email');
$ci->email->send();

Don't worry, this seems to be confusing to most new CI users, especially those new to OOP

#5
[eluser]Donny Kurnia[/eluser]
I think this is not bug, but the way CI work.

$this->load->model, $this->load->library, and $this->load->helper should only used in controller, since it is the duty of controller to load required component.

If you want to load other model/library/helper from non-controller, such as library, model, or view, then you should do it by getting CI instance and use it to load required component.

The workaround you write is actually the way of CI work. You can open up build in library to see how it call other library and helper. One example, open up the Form_validation.php file in system/library folder. It will have this in the class constructor:

$this->CI =& get_instance();
...
$this->CI->load->helper('form');

So, given core library use this technique, then I can assume that this is CI way to load component from non-controller component.

#6
[eluser]bretticus[/eluser]
I completely disagree. That is, I disagree with the fundamental design of CI that one cannot reference core libs, etc from the $this variable from within a model (if this is, in fact, true.)

Essentially, all that should be required of the controller at the basic level is to get the data to submit to the view. It controls what happens when I submit a particular URL. Nothing more. Ideally, a controller should be thin, and models fat. The Model in CI can essentially do everything that a controller can. In fact, according to php core documentation, this is the whole purpose of the one method that Model calls: _assign_libraries.

Quote:/**
* Assign Libraries
*
* Creates local references to all currently instantiated objects
* so that any syntax that can be legally used in a controller
* can be used within models.
*
* @access private
*/

Unfortunately, it would appear that this method messes up any libraries that are called in the Model constructor if called BEFORE calling parent::Model(). I just ran across this issue and had the same question. By placing my code after the parent::Model() call, I was able to use the library from my model:

Code:
function Journals() {        
        parent::Model();
        // debugging
        $this->load->library('firephp');
        $this->firephp->setEnabled($this->config->item('firephp_enabled'));
    }

Disclaimer. I haven't thoroughly investigated this and I also call the firephp library from the same controller that calls this model (not all of my controllers load firephp, thus, I need to load it in this model.)

#7
[eluser]Calvin Froedge[/eluser]
I was banging my head against the wall for hours trying to figure out why I couldn't reference or extend a model or library.

Other than the "rules" of codeigniter, what's the sense / reasoning behind not being able to create a base model that extends model?


Digg   Delicious   Reddit   Facebook   Twitter   StumbleUpon  


  Theme © 2014 iAndrew  
Powered By MyBB, © 2002-2021 MyBB Group.