It can be a bit tricky at times, but it really comes down to the CI_Controller being a singleton and setting up some simple shortcuts to the CI_Controller instance. The CI_Controller singleton is setup like this (some comments and whitespace removed to trim down the code):
PHP Code:
class CI_Controller {
/**
* Reference to the CI singleton
*/
private static $instance;
public function __construct()
{
self::$instance =& $this;
// Assign all the class objects that were instantiated by the
// bootstrap file (CodeIgniter.php) to local class variables
// so that CI can run as one big super object.
foreach (is_loaded() as $var => $class) {
$this->$var =& load_class($class);
}
$this->load =& load_class('Loader', 'core');
$this->load->initialize();
log_message('info', 'Controller Class Initialized');
}
/**
* Get the CI singleton
*/
public static function &get_instance()
{
return self::$instance;
}
}
To ensure the same instance is retrieved in most contexts, CodeIgniter.php defines the global get_instance() function as follows:
PHP Code:
// Load the base controller class
require_once BASEPATH.'core/Controller.php';
/**
* Returns current CI instance object
*/
function &get_instance()
{
return CI_Controller::get_instance();
}
When you load a model or library, the loader gets the CI_Controller instance, then checks whether the model/library has already been loaded on that instance. If it has already been loaded, the loader returns without doing anything else, unless you supply an alternate name in the call to the loader. If it has not been loaded, or you supply an alternate name for the library/model, it loads the library/model and assigns it to the CI_Controller instance as a property named with the name of the library/model or the alternate name.
The bulk of the code in CI_Model is a magic method to access the CI_Controller instance if a method or property isn't defined on the model:
PHP Code:
class CI_Model {
public function __construct()
{
log_message('info', 'Model Class Initialized');
}
/**
* Allows models to access CI's loaded classes using the same
* syntax as controllers.
*/
public function __get($key)
{
// Debugging note:
// If you're here because you're getting an error message
// saying 'Undefined Property: system/core/Model.php', it's
// most likely a typo in your model code.
return get_instance()->$key;
}
}