Welcome Guest, Not a member yet? Register   Sign In
Why can't I load a library from inside a Model (anymore)?
#1

[eluser]gustavofarias[/eluser]
I used to call the code below to send email from within one of my Model classes (CI 1.6.1)

Code:
$this->load->library('email');
$config['protocol'] =  "smtp";
(...)
$this->email->initialize($config);
$this->email->from("[email protected]");
$this->email->to("[email protected]");
$this->email->subject("some");
$this->email->message("some");
$this->email->send();

I'm currently using CI 1.7.1 and now I get the error

Message: Undefined property: MyModel::$email
Fatal error: Call to a member function initialize() on a non-object

The very same code works if I put email in the list of autoload libraries, or if a initialize it in in a controller prior to calling the Model.
#2

[eluser]TheFuzzy0ne[/eluser]
Any initialised libraries will not be available from within any of your models if those models were loaded before it.

To access the email library, you'd need to do something like this:
Code:
$CI =& get_instance();
$CI->load->library('email');
$config['protocol'] =  "smtp";
(...)
$CI->email->initialize($config);
$CI->email->from("[email protected]");
$CI->email->to("[email protected]");
$CI->email->subject("some");
$CI->email->message("some");
$CI->email->send();

Alternatively, you could call $this->_assign_libraries() from within the model, and the Email library would then be available to your model.
#3

[eluser]wiredesignz[/eluser]
[quote author="TheFuzzy0ne" date="1237529606"]Any initialised libraries will not be available from within any of your models if those models were loaded before it.
[/quote]

Actually the library loader calls _assign_to models() which calls each registered model _assign_libraries() method in turn so the library should be available.

@OP, Just a tip to remember that "$this->load" refers to the loader at the controller level and does not refer to the model at all.
#4

[eluser]TheFuzzy0ne[/eluser]
[quote author="wiredesignz" date="1237531542"]Actually the library loader calls _assign_to models() which calls each registered model _assign_libraries() method in turn so the library should be available.[/quote]

Actually, no. This code takes care of that.

Code:
if (in_array($name, $this->_ci_models, TRUE))
{
    return;
}

If the model is loaded, return...

[quote author="wiredesignz" date="1237531542"]@OP, Just a tip to remember that "$this->load" refers to the loader at the controller level and does not refer to the model at all.[/quote]

Again, no it doesn't... $this refers to the object containing the method being called. If you call $this from within the model method, then $this refers to the model.
#5

[eluser]wiredesignz[/eluser]
Fuzzy, the $load variable in the model is a reference to the controller loader class and has nothing to do with the model itself.

If you doubt this please go look at the code in the Model class.

Models merely have controller variables assigned to them, and as such they have no loader of their own.

Any library loaded in a model is actually loaded to the controller object first and then assigned forward to all models.
#6

[eluser]TheFuzzy0ne[/eluser]
[quote author="wiredesignz" date="1237563078"]Fuzzy, the $load variable in the model is a reference to the controller loader class and has nothing to do with the model itself.[/quote]

I'm not debating that, what I'm saying is that _assign_libraries() is only called once by the loader class. It's not called automatically on each model every time a a new library/model is loaded. If it is, please show me where. The code I pasted will cause the function pointer to return if that particular model is already loaded. _assign_libraries comes after that, so it goes without saying that if the model is already loaded, _assign_libraries is not called again, unless of course you call it manually. Do you see what I am getting at now?

[quote author="wiredesignz" date="1237563078"]If you doubt this please go look at the code in the Model class.[/quote]

Done! I must be missing something...

[quote author="wiredesignz" date="1237563078"]Models merely have controller variables assigned to them, and as such they have no loader of their own.[/quote]

Indeed, and they only get the controller variables assigned to them when they are loaded.

Code:
$this->load->model('model_1'); # Loads model 1
$this->load->model('model_2'); # Loads the second model.

# Model 2 now has access to model 1, but model 1 is unaware of model 2's existance
# as it was loaded after _assign_libraries was called. If to be access the second model
# from model 1, in the model you'll need to do:

$CI =& get_instance();
$CI->model_2->get();

# Or you can just call _assign_libraries from within the controller method

$this->model_1->_assign_libraries();

[quote author="wiredesignz" date="1237563078"]Any library loaded in a model is actually loaded to the controller object first and then assigned forward to all models.[/quote]

Yes. I can't argue with that, as it is a fact. What I am saying is that _assign_libraries is only ever called once automatically by CodeIgniter.
#7

[eluser]wiredesignz[/eluser]
Check line 99 of the CI_Loader class which is the library loader method and you will see...
Code:
$this->_ci_assign_to_models();
...is called EVERY time a library is loaded.

Then look at line 1017 for the assign_to_models method....
Code:
/**
* Assign to Models
* Makes sure that anything loaded by the loader class (libraries, plugins, etc.)
* will be available to models, if any exist.
*/

Every library loaded is assigned to all of the currently loaded models.
#8

[eluser]TheFuzzy0ne[/eluser]
Man, do I feel like a muppet... I totally forgot the subject and thought we were discussing models loading other models, not models loading libraries. Sorry about that...




Theme © iAndrew 2016 - Forum software by © MyBB