Welcome Guest, Not a member yet? Register   Sign In
Loading libraries in controller vs. loading in CI instance
#1

[eluser]Maarten Troonbeeckx[/eluser]
I'm a bit confused... :/

In my controller I do the following:

Code:
class Index extends Controller
{

    ...

    public function index()
    {
        $this->load->library('Shop_Front', null, 'shop');
    }

    ...

}

Then in one of my libraries, this happens:

Code:
class MY_Library
{

    ...
    
    $CI =& get_instance();
    $CI->load->library('Shop', null, 'shop');

    ...

}

I was under the impression that I would override the 'shop' object name, since I define it in two places. I thought $CI->shop == $this->shop (in controller)...

So not every library you load in the controller is available in the CI instance or vice versa, right?

I'm clearly missing something here...
Can somebody enlighten me a bit Wink

Grtz, M.
#2

[eluser]WanWizard[/eluser]
No, the loader refuses to load if the object already exists.

This is indeed quite confusing, and a consequence of the (still present) support for PHP4.
To make sure CI objects are available the are assigned to the class (controller, library) when it loads. Every thing you load after that is visible within the scope you load it, but not outside.

So:
Code:
class MY_Controller
{
    ...
    $this->load->library('MY_LibraryA');
    $this->load->library('MY_LibraryB');
    $this->load->library('MY_LibraryC');
    ...
    $this->My_LibraryB->test();
}

class MY_LibraryB
{
    ...
    function test()
    {
        $this>MY_LibraryA->method(); // works
        $this>MY_LibraryC->method(); // doesn't work
    }
    ....
}

In PHP5, you can overload the __get() method to check if the requested class property is defined, and if not, if the CI object has a property by the requested name. If so, assign it to $this and turn it.

That would mean all objects known to the CI object at any given time are immediately available in all classes, they are dynamically created as soon as they are referenced.

You could even go one step further, and dynamically load the class when the CI object does not exist but the class file does. But that requires a change to the loader class and a decent way of determining what a library is and what a model (or other class). i.e. the issue of namespace.
#3

[eluser]Maarten Troonbeeckx[/eluser]
WanWizard,

Tnx for your reply.
I understand what you are saying, partially... Smile

Here's my code again, slightly different:


Code:
class Index extends Controller
{

    ...

    public function index()
    {
        $this->load->library('Shop_Front', null, 'shop');
        var_dump($this->shop);
    }

    ...

}

Then in one of my libraries, this happens:

Code:
class Shop_Front
{

    ...
    
    public function method()
    {
        $CI =& get_instance();
        $CI->load->library('Shop', null, 'shop');
        var_dump($CI->shop);
    }

    ...

}

Why does var_dump() in the Controller show me Shop_Front and why does var_dump() in the library show me Shop? Shop_Front and Shop are different classes/libraries...

Why does the Loader still loads Shop as a different class while the shop property in CI already contains an instance of the Shop_Front class?

Grtz, M.
#4

[eluser]WanWizard[/eluser]
Good question.

I've had a look at the Loader class code, which checks on duplicate load requests by library filename, and if it is found to be loaded before, a double check on object name is done.

In your case, you load a different library file, so the first test is negative (it has not been loaded before). It therefore loads the requested library, and instantiates the object (with the override name in your case). The instantiation method doesn't check again if the object name already exists, so your second load will overwrite your first, after which in both methods the object will now point to 'Shop'.
#5

[eluser]Maarten Troonbeeckx[/eluser]
Just thinking out loud.

When I just want to load a class into a variable using the CI loading mechanism, wouldn't it be useful to do something like this:

Code:
$objectInstance = $CI->load->library('MY_Class', null, true);

A bit like returning the view into a variable instead of outputting to the browser when using true as the third parameter.

You can avoid clashes in the CI instance this way...
Or would this be against best CI practices?

I'm using the __get() solution you proposed now, tnx for sharing!

Grtz, M.
#6

[eluser]WanWizard[/eluser]
The loader doesn't support that, but there is an (undocumented) work-around:
Code:
$mylib =& load_class('MyLibrary'); // works only for libraries

For CI 2.0, you can use this for other classes as well:
Code:
$mymodel =& load_class('MyModel', 'class_directory');
where 'class_directory' is a directory in the APPPATH or BASEPATH.




Theme © iAndrew 2016 - Forum software by © MyBB