1

My Application works with Third Party Applications. The Thirdparty Application is a Library Class, which is locaded in application/libraries/NAMEOFTHECLASS/main.php.

I have a Library the modulehandler which has the job to handle the ThirdParty-Classes.

The Third Party Class looks like this:

 class main {

var $name;
var $description;
var $saphir;
var $location;

public function init($config = array()) {
    $this->name = $config['name'];
    $this->description = $config['description'];
    $this->saphir =& get_instance();
    $this->location = $config['location'];
}

public function getFormElements() {
   $html = $this->saphir->load->file($this->location.'/tpl/main.html',true);
   $this->saphir->load->library('parser');

   $data = array(
        'name' => $this->name,
        'description' => $this->description
        );

   $html = $this->saphir->parser->parse_string($html, $data, TRUE);
   return $html;
}

public function validation($post_data)
{
     $array = explode(',', $post_data);
     if($post_data != is_array($array) )
         return array("error" => array("name" => $this->name, "message" => "Bitte geben Sie nur eine Kommagetrennte Liste an"));

}

public function handleData($post_data) {
    $array = explode(',', $post_data);
    $return = array();
    foreach($array as $key => $val) {
        array_push($return, array("data" => $val));
    }
    return $return;
}
}

In the Module Handler i load in a foreach every thirdparty class which i need and call a function.

Zb in my ModuleHandler Class here is the method to get Form Elements from the Thirdparty Scripts:

    private function getForm()
    {

       $form_data = array();
        foreach($this->schema as $schema) {
            $config = array("type" => $schema['type'], "name" => $schema['name'], "description" => $schema['description'], 'location' => 'application/libraries/thirdparty/cm_system/'.$schema['type']);
            $type = $schema['type'];

            if($this->edit) {
                $value = $this->info;
                $val = array();
                foreach($value->ELEMENT as $element)
                {
                    $holder = (string)$element;
                    array_push($val, $holder);
                }
                $value = $val;
            }
            else  {
                $value = "";
            }

            $ins = $this->CI->load->library('thirdparty/cm_system/'.$type.'/main');
            $this->CI->main->init($config);

            $form_elements = $this->CI->main->getFormElements($value); 

            array_push($form_data, $form_elements);

        }
        return $form_data;
    } 

The problem is, that every thirdparty Class has the name main. And i get the error that i cant redeclare class main. Is there a way to unset the loaded class?

I tried it already with unset. But it dont works.

1
  • why not just switch/case $type and load Classes with different names from the same folder but with the same interface (strategy pattern)? the effort is minimal and it would be cleaner than fiddling around with CI internal classes. Commented Mar 5, 2014 at 23:26

3 Answers 3

1

You can unload the library using a small hack, to do this you have to extend the Loader

Create a file in appilication/core/MY_Loader MY is the prefix coming from $config['subclass_prefix']

class MY_Loader extends CI_Loader {

public function unload_library($name) {
    $name = strtolower($name);
    foreach ($this->_ci_loaded_files as $key => $path) {
        $file_name = basename($path);
        $value = substr($file_name, 0, strlen($file_name) - 4);
        if (strtolower($name) == strtolower($value)) {
            unset($this->_ci_loaded_files[$key]);
            $CI = & get_instance();
            unset($CI->$name);
        }
    }
}

}

Now you can unload a library using

$this->load->unload_library('YOUR_LIB_NAME');
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for your response. I create the new Loader Class but if i run this code in a foreach: $class = 'thirdparty/cm_system/'.$type.'/main'; $this->CI->load->library($class); $this->CI->main->init($config); $form_elements = $this->CI->main->getFormElements($value); array_push($form_data, $form_elements); $this->CI->load->unload_library("main"); I get this error Fatal error: Cannot redeclare class main in libraries/thirdparty/reg_input/main.php on line10 Thanks
Edit: I tested the following code: $class = 'thirdparty/cm_system/'.$type.'/main'; $this->CI->load->library($class); $this->CI->main->init($config); $form_elements = $this->CI->main->getFormElements($value); array_push($form_data, $form_elements); $this->CI->load->unload_library("main"); $this->CI->main->getFormElements($value); And i get after the unload a error. THat main is not a object, thats correct. But i get also the same error as in the top Thank you
Yes you are right my code will only __destruct the object but php already loaded the file so you cannot declare the same name again, i used my code for reloading the lib again but your case no way :(
0

You can do this:

$ins = $this->CI->load->library('thirdparty/cm_system/'.$type.'/main', null, $type);

If you navigate to /ci/system/core/loader.php you will find public function library() on line #194:

public function library($library = '', $params = NULL, $object_name = NULL)

The third parameter allows you to specify a unique object name to avoid collisions.

So now you can simply call:

$this->CI->load->library('thirdparty/cm_system/'.$type.'/main', null, $type);

// and use it like:
$this->$type->someFunction();

1 Comment

Thanks for your Respone. If I Run the function with this Code: $class = 'thirdparty/cm_system/'.$type.'/main'; $this->CI->load->library($class, null, $type); $this->CI->$type->init($config); $form_elements = $this->CI->$type->getFormElements($value); array_push($form_data, $form_elements); unset($this->CI->$type); I get this error: Fatal error: Cannot redeclare class main in /libraries/thirdparty/reg_input/main.php on line 10 Thanks
0

Since CI does not use namespaces, there is no way to make this work as it is.

It's not a CI limitation, it's a PHP one. CI include the file, so if you include 2 files with a class Main, it will of course crash.

The easiest and cleanest solution is to name your class and the associated file with the same name as the folder.

ie:

$ins = $this->CI->load->library('thirdparty/cm_system/'.$type.'/'.$type);

Having the "main" class named the same as the folder is pretty common.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.