Welcome Guest, Not a member yet? Register   Sign In
Loader::_ci_load_class can't find extended 'MY_' libraries when using $_ci_library_paths
#1

[eluser]maikens[/eluser]
I have a CI install with 2 apps in it, plus a 'common' folder which holds shared models, libraries, helpers the two apps need to use.

Code:
application/
app/
admin/
common/
    ...
    index.php
    admin.php

In order to load everything up correctly in the system Controller.php file, I extend it using core/MY_Controller. I do this in the MY_Controller construct like so:

Code:
public function __construct() {  
  
    // This allows us to store our models, helpers, libraries, and other files that
    // all apps on this CI installation share in a common folder to avoid code duplication
    $loader =& load_class('Loader', 'core');
    $loader->add_package_path(COMMONPATH, array('model', 'helper', 'library'));
  
    parent::__construct();
    // ... etc ...

I also extend Loader in the same manner, so I can add_package_path prior to instantiating the Controller class (it would throw an error when trying to load config before calling Controller::__construct(), so I override add_package_path to allow loading specific things - in this case, models, helpers, and libraries')

The problem is, in Loader::_ci_load_class(), when it goes through the _ci_library_paths array to search for the library, it doesn't try appending the 'MY_' prefix when searching, and so it is not loaded as an extension of the Session class.

Relevant code in Loader::_ci_load_class() below:

Code:
// We'll test for both lowercase and capitalized versions of the file name
  foreach (array(ucfirst($class), strtolower($class)) as $class)
  {
   $subclass = APPPATH.'libraries/'.$subdir.config_item('subclass_prefix').$class.'.php';

   // Is this a class extension request?
   if (file_exists($subclass))
   {
    $baseclass = BASEPATH.'libraries/'.ucfirst($class).'.php';

    if ( ! file_exists($baseclass))
    {
     log_message('error', "Unable to load the requested class(from libraries): ".$class);
     show_error("Unable to load the requested class(from libraries): ".$class);
    }

    // Safety:  Was the class already loaded by a previous call?
    if (in_array($subclass, $this->_ci_loaded_files))
    {
     // Before we deem this to be a duplicate request, let's see
     // if a custom object name is being supplied.  If so, we'll
     // return a new instance of the object
     if ( ! is_null($object_name))
     {
      $CI =& get_instance();
      if ( ! isset($CI->$object_name))
      {
       return $this->_ci_init_class($class, config_item('subclass_prefix'), $params, $object_name);
      }
     }

     $is_duplicate = TRUE;
     log_message('debug', $class." class already loaded. Second attempt ignored.");
     return;
    }

    include_once($baseclass);
    include_once($subclass);
    $this->_ci_loaded_files[] = $subclass;

    return $this->_ci_init_class($class, config_item('subclass_prefix'), $params, $object_name);
   }

   // Lets search for the requested library file and load it.
   $is_duplicate = FALSE;
   foreach ($this->_ci_library_paths as $path)
   {
    $filepath = $path.'libraries/'.$subdir.$class.'.php';

    // Does the file exist?  No?  Bummer...
    if ( ! file_exists($filepath))
    {
     continue;
    }

    // Safety:  Was the class already loaded by a previous call?
    if (in_array($filepath, $this->_ci_loaded_files))
    {
     // Before we deem this to be a duplicate request, let's see
     // if a custom object name is being supplied.  If so, we'll
     // return a new instance of the object
     if ( ! is_null($object_name))
     {
      $CI =& get_instance();
      if ( ! isset($CI->$object_name))
      {
       return $this->_ci_init_class($class, '', $params, $object_name);
      }
     }

     $is_duplicate = TRUE;
     log_message('debug', $class." class already loaded. Second attempt ignored.");
     return;
    }

    include_once($filepath);
    $this->_ci_loaded_files[] = $filepath;
    return $this->_ci_init_class($class, '', $params, $object_name);
   }

  } // END FOREACH

This feels like a core bug to me, but perhaps the way I override or load the Loader class / add_package_path method is wrong?

PS my CodeIgniter version is 2.1.0
#2

[eluser]jonez[/eluser]
Put die statements in each step to see where your conditions aren't catching the correct files/paths. It's not a core bug since it functions correctly without your modifications.
#3

[eluser]maikens[/eluser]
I resolved this by overriding _ci_load_class - simply a copy/paste of the superclass method with this modification:

Code:
// We'll test for both lowercase and capitalized versions of the file name
    foreach (array(ucfirst($class), strtolower($class)) as $class)
    {
      $subclass = APPPATH.'libraries/'.$subdir.config_item('subclass_prefix').$class.'.php';

      // ADDED THESE TWO LINES:
      if(!file_exists($subclass))
        $subclass = COMMONPATH.'libraries/'.$subdir.config_item('subclass_prefix').$class.'.php';
  
      // Is this a class extension request?
      if (file_exists($subclass))
      {
        $baseclass = BASEPATH.'libraries/'.ucfirst($class).'.php';

COMMONPATH resolves to application/common. It couldn't find the subclasses because it was looking in the wrong place. The whole point of add_package_path was to add that place to look, so I find it a little odd that they don't check the _ci_library_paths at this point in the method... but then again my modifications are a little different than what the core developers seemed to have intended for add_package_path().




Theme © iAndrew 2016 - Forum software by © MyBB