Welcome Guest, Not a member yet? Register   Sign In
Load class in outside directory in CI application path
#1

[eluser]Marcus Cavalcanti[/eluser]
Hi CI people!

I have an application structure like example below:

Code:
[root]
- css
- img
- js
- swf
- system
   - application
      - backend
         - config
         - controllers
         - errors
         - helpers
         - ... (more)
      - frontend
         - config
         - controllers
         - errors
         - helpers
         - ... (more)
      - models
      - services
         - test.php
   - cache
   - codeigniter
   - database
   - fonts
   - helpers
   - language
   - libraries
   - logs
   - plugins
   - scaffolding

The 'services' directory in application path has many classes to manage common business logic in my application domain, so i need to use this classes in my two applications: frontend and backend

The problem begins when i try to load any class, with this code:

Controller
Code:
<?php

class Testing extends Controller {

    function Testing()    {
        parent::Controller();    
    }
    
    function index() {        
        $this->load->library('../../services/test');
        $ret = $this->test->testando();        
                
        $this->load->view('container');
    }
}
?>

The error returned:

Code:
Fatal error: Cannot redeclare class Test in D:\projetos\paiva\src\site\system\application\services\test.php on line 3

system/application/services/test.php

Code:
class Test {
        function testando () {
            return "shit happens";
        }
    }

The curious side is that if i'm trying to load models, in 'models' path, i dont have any problem, i only have troubles with the 'services' path.

Anyone knows how to load classes in outside directory?

Thanks.
#2

[eluser]Brandon Dickson[/eluser]
You might try

Code:
function get_class( $path )
{
      require_once( realpath( $path.'.php' ) );

      $name = end( explode( '/', $path ) );

      $class = ucfirst( $name );

      $ci =& get_instance();

      $ci->$name =& new $class();

      return $ci->$name;

}

For a start anyway, thats assuming your naming your files with the class name, and the classes with the first letter capitalized.

In the path string, '.', will resolve to any folder in your include path ( generally the folder where your index.php file resides is an include path )


-Brandon
#3

[eluser]Marcus Cavalcanti[/eluser]
Thanks for your reply Brandon.

Your function works, but the type returned of the new class instantiated is the same type of the current controller.

Code:
class Test extends Controller {

    function Test()    {
        parent::Controller();    
    }
    
    function index() {        
        $ret = $this->get_ci_class("system/application/services/test");
        echo "<pre>";        
        print_r(get_class_methods($ret));
        echo "</pre>";        
        die;
                
        $this->load->view('container', $this->data);
    }
    
    function get_ci_class( $path ) {
        require_once( $path.'.php' );

        $name = end( explode( '/', $path ) );

        $class = ucfirst( $name );
        
        $ci =& get_instance();
        
        die("$name : $class");

        $ci->$name =& new $class();
        
        return $ci;
    }
}

The follow code prints the methods of Test Controller, not the methods of Test 'Service'.
#4

[eluser]Marcus Cavalcanti[/eluser]
sorry, the problem is in my code.

the correct get_ci_class() method:


Code:
function get_ci_class( $path ) {
        require_once( $path.'.php' );

        $name = end( explode( '/', $path ) );

        $class = ucfirst( $name );
        
        $ci =& get_instance();
        
        $ci->$name =& new $class();        
        
        return $ci->$name;
    }
#5

[eluser]Brandon Dickson[/eluser]
Marcus,

In the function get_ci_class() your returning the 'super object' not the new instance of the loaded class, try:

Code:
return $ci->$name;

Also, $ci->$name 'caches' the new class instance as a property of the super object, so you could just as easily call $this->name (assuming your inside a controller) at any time after you have called get_ci_class().

This effectively makes the new class a singleton, as creating another instance of the same class with get_ci_class() will overwrite the previous instance.

If you just want to load instances and not have them accessible via $this->name, then replace

Code:
$ci =& get_instance();
$ci->$name =& new $class();
return $ci->$name;

with

Code:
return new $class();

But note that as soon as you loose the variable, you've lost the instance.

Check out my post on loading multiple controllers
(I think you might be doing this, but I not sure from the example ):

http://ellislab.com/forums/viewthread/81249/

And also note that from PHP's perspective everything that happens on a server call happens in one process, so if you have 2 class definitions both named Test, even if they are in separate files, you will get errors, there's not really a fix for this, unless you tried to dynamically change the class name before the contents of the included file are processed by PHP. (I've experimented with this, but it's not really a viable option.)

-Brandon

Edit: I just noticed your reply after I submitted this, good luck!




Theme © iAndrew 2016 - Forum software by © MyBB