Third party packages & model loading via MX
Hi again,
I am revisiting some code I did a few months back, and am unhappy that I needed to duplicate some functionality in the application folder and the fuel/modules folder - specifically for a model and 2 libraries. More or less the same stuff was happening in 2 places (eg application/libraries and fuel/modules/sphider/libraries, and application/models and fuel/modules/sphider/models), and this seemed unnecessary. Browsing through the CI user guide, I noticed the packages feature, and thought I saw a solution.
So in my controllers __construct() I used
$this->load->add_package_path(APPPATH.'third_party/sphider/');
$this->load->model('sphider_model');
$this->load->library('sphiderlib');
$this->load->remove_package_path();
This code is in 2 controllers - one in /application and one in a fuel module.
Both now throw this error:
An Error Was Encountered
Unable to locate the file: sphider_model.php
This error happens in MX/Modules.php. Sniffing around the CI forum, I saw that there were others having issues loading package models and languages with MX version 5.3.5 (Fuel uses 5.3.5, albeit with modifications). The most recent MX is 5.4 (I think).
If the order of the library and model loading after the add_package_path() are swapped, the error message is the same, so I think the library load is working, but the model isn't.
I tried replacing the MX/Modules.php with the 5.4 version, but this got me a different error Unable to load the requested file: helpers/fuel/fuel_helper.php
and I'm now wondering if I'm getting into something I won't be able to fix categorically in Fuel, as other MX classes are Fuel customised (Config, Lang and Loader), and replacing all but these leads to deeper PHP errors.
Comments
https://bitbucket.org/wiredesignz/codeigniter-modular-extensions-hmvc/changeset/652e85cc40a3#chg-third_party/MX/Loader.php
Would you mind trying the following to see if it works and if so I can add it for the next release:
In third_party/MX/Loader.php, replace the _init method with the following:
/** Initialize the loader variables **/ public function initialize($controller = NULL) { parent::__construct(); if (is_a($controller, 'MX_Controller')) { /* reference to the module controller */ $this->controller = $controller; /* references to ci loader variables */ foreach (get_class_vars('CI_Loader') as $var => $val) { if ($var != '_ci_ob_level') { $this->$var =& CI::$APP->load->$var; } } } else { parent::initialize(); } /* set the module name */ $this->_module = CI::$APP->router->fetch_module(); /* add this module path to the loader variables */ $this->_add_module_paths($this->_module); } /** Add a module path loader variables **/ public function _add_module_paths($module = '') { if (empty($module)) return; foreach (Modules::$locations as $location => $offset) { /* only add a module path if it exists */ if (is_dir($module_path = $location.$module.'/') && ! in_array($module_path, $this->_ci_model_paths)) { array_unshift($this->_ci_model_paths, $module_path); } } }
Then in the third_party/MX/Controller.php file change:
$this->load->_init();
TO
$this->load->initialize($this);
Actually, the correct (Fuel) way to achieve what I want is to incorporate the front-end views in the Fuel module I've created - that will complete the DRY refactoring I'm after, although having a working Third Party folder would be nice too!
Here be dragons.
I have this in /fuel/modules/sphider/controllers/search.php
$page_init = array('location' => 'search/index'); $this->load->module_library(FUEL_FOLDER, 'fuel_page', $page_init); $this->fuel_page->add_variables($data); $this->fuel_page->render();
which of course finds the view in /application/views/search/index.php, but I want to point it to /fuel/modules/sphider/views/search/index.php
I can render the basic views like so:
$this->load->module_view(SPHIDER_FOLDER, 'themes/default/index',$data);
but obviously I would like them sandwiched in the main layout view, with the fuel_vars included.
Will I need to use a different render layout functionality to achieve this?
public $view_location = 'sphider';
$this->load->module_view(SPHIDER_FOLDER, 'themes/default/index',$data);
allows variables ($data) to be passed and rendered, whereas
$page_init = array('location' => 'search/index'); $this->load->module_library(FUEL_FOLDER, 'fuel_page', $page_init); $this->fuel_page->add_variables($data); $this->fuel_page->render();
displays the template but kills off the passed variables (regardless of $view_location's presence) - eg a loop displays "undefined variable" messages using this render method.
I think I'll have to work out how the blog module uses templates, and try and work back.
The problem with studying the blog module though, is it is quite difficult to follow and relate to one's own tasks.
$this->load->module_view(SPHIDER_FOLDER, 'themes/default/index',$data);
and then adding the template blocks individually to the view as a sandwich:
<?php $this->load->view('_blocks/header', array('css' => '', 'page_title' => 'Search results'), FALSE);?> <?php $this->load->view('_blocks/mast');?> <!--sphider_noindex--> <div id="page-content" class="grid_8"> <div class="pad"><h1><?php echo fuel_var('page_title', ''); ?></h1> ... original view code here ... </div> </div> <div id="sidebar" class="grid_4"> <div class="pad sidebar"> <div id="tweets"></div> </div> </div> <div class="clear"></div> <!--/sphider_noindex--> <?php $this->load->view('_blocks/footer', array('js' => ''), FALSE);?>
This makes the view a template like the "main" layout view, but it's the closest yet to what I want. Note that the sandwiching blocks are passed arrays with the values of the missing fuel vars (not doing this results in "Undefined variable" messages for css and js)
Now I need to eliminate the FUEL MARKER comments.
define('USE_FUEL_MARKERS', FALSE);
If you need to retrieve the variables for a particular URI location, you can use the following:
$vars = $this->fuel_pagevars->retrieve(uri_path());
Should have resigned myself to doing this earlier, but it all seemed rather verbose compared to what's required to get an application view right. After throwing out all the Blog related stuff the _render() method only came to 16 lines long, so it was hardly much effort! I didn't bother extending the controller as per the Blog, I just added the _render() to the controller I was using, so that cut some overhead.
Thanks for your patience!
I've used Ion auth a few times with Fuel. You might be interested in this hooks solution I used recently