CodeIgniter Forums
HMVC loading driver across modules - Printable Version

+- CodeIgniter Forums (
+-- Forum: External Resources (
+--- Forum: Addins (
+--- Thread: HMVC loading driver across modules (/showthread.php?tid=65041)

HMVC loading driver across modules - reanvdm - 04-22-2016

Have the following (simplified) setup:



Am attempting to use Queue driver library inside of Test controller - ie across modules.
The basic load of driver library works, but the driver library is unable to find/load its child drivers/drivername.

This works in Test.php if Queue::add is a stub (ie not doing anything)

PHP Code:
function test()
$this->queue->add('test message');

But, when the library then tries to load an individual driver (e.g. to add an item into a queue), the load fails: (in Queue/Queue.php)

PHP Code:
function add($payload='')
//...ignore code that picks which driver to use - assume its queue_a
$this->queue_a->add_message($payload); //this fails, Queue_a.php cannot be found to load

The problem seems to be that HMVC overrides the core Loader.php file - but the code in core/libraries/Driver.php that locates individual driver child classes is not HMVC aware, and does not use the Loader class.

My first thought for solution is to extend core/libraries/Driver.php in new file MX_Driver.php:

PHP Code:
public function __get($child)
   //establish path of child driver     
$lib_name get_class($this);
   $reflector = new ReflectionClass($lib_name);
   $class_path  dirname($reflector->getFileName());
   $lib_path dirname($class_path);
   $module_path dirname($lib_path);

//temp add the path for CI loader to find
   // Try to load the driver
   return $this->load_driver($child);
   // Reset things to clean up

Have a feeling this has been solved before however?

RE: HMVC loading driver across modules - orionstar - 04-22-2016

I had this problem too, put the method below to your main driver file!
This will override the default driver loading method.

PHP Code:
public function load_driver($child)
// Get CodeIgniter instance and subclass prefix
$prefix config_item('subclass_prefix');

    if ( ! isset(
// Get library name without any prefix
$this->lib_name str_replace(array('CI_'$prefix), ''get_class($this));

// The child will be prefixed with the parent lib
$child_name $this->lib_name.'_'.$child;

// See if requested child is a valid driver
if ( ! in_array($child$this->valid_drivers))
// The requested driver isn't valid!
$msg 'Invalid driver requested: '.$child_name;

// Search the child only in the current folder...
$path realpath(dirname(__FILE__));

// Does the file exist?
$file $path '/drivers/' $child_name '.php';
    if (
// Include source

    if (
$class_name $child_name;
$msg 'Unable to load the requested driver: '.$class_name;

// Instantiate, decorate and add child
$obj = new $class_name();
$this->$child $obj;

RE: HMVC loading driver across modules - reanvdm - 04-23-2016

Its interesting that the default CI driver->load($child) method goes looking in all Package paths, when a child driver by convention lives in sub-directory of the parent. I can see your code resolves that neatly.

I simply altered the shorter __get($child) magic method because there is less code to override - so less chance of clash with future CI changes. I guess HMCV already changes a lot of core code anyhow and this risks that load($child) calls still fail.

Another small change I needed to make  - from line 196 of third_party/MX/Modules.php - to load drivers/libraries across modules:

PHP Code:
foreach($modules as $module => $subpath
$fullpath $location.$module.'/'.$base.$subpath;

    if (
$base == 'libraries/' OR $base == 'models/')
is_file($fullpath.ucfirst($file_ext))) return array($fullpathucfirst($file));
         * EDITS
         * check for drivers loaded across modules in a subdir with same name as file
         * the core library loader does the same trick, but MX one does not
else if($base == 'libraries/')
$fullpath $fullpath.ucfirst($file).'/'//file here is /classname
if(is_file($fullpath.ucfirst($file_ext))) return array($fullpathucfirst($file));
         * END EDIT
/* load non-class files */
if (is_file($fullpath.$file_ext)) return array($fullpath$file);

This allows me to load a driver with $this->load('module/driver') across modules as shown in the code above.

RE: HMVC loading driver across modules - reanvdm - 04-25-2016

For future reference: Note there are two possible errors in the code posted by Orionstar above:

Line 60:
PHP Code:
$msg 'Unable to load the requested driver: '.$class_name

At that point $class_name is not defined, should be $child.

Also, in line 44

$path = realpath(dirname(__FILE__));

__FILE__ refers to the directory location of Class where the function is defined, ie the parent - not of the class that inherits the definition.
This can be solved with:

PHP Code:
$c = new ReflectionClass($this);
$path realpath(dirname($c->getFileName())); 

RE: HMVC loading driver across modules - orionstar - 04-25-2016

Thank you to point out the mistakes in the code.