Third party packages & model loading via MX

edited May 2012 in Bug Reports
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

  • edited 4:14AM
    I tried upgrading to 5.4 a while back and it proved to be too much to fix at the time. I took a look at some of the commits though and found one regarding package paths.
    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);
  • edited 4:14AM
    Sorry that didn't help.

    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.
  • edited May 2012
    Further to the above, I have moved all the libraries, controllers, views and so forth into my advanced module, configured the routing and it's all working except... I'm not sure how to configure the view location.

    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?
  • edited 4:14AM
    Try adding this to your controller:
    public $view_location = 'sphider';
  • edited 4:14AM
    Using

    $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.
  • edited May 2012
    What sort of works (albeit with __FUEL_MARKER__ comments aplenty) is loading the view with
    $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.
  • edited 4:14AM
    You can define a "USE_FUEL_MARKERS" constant and set it to FALSE to prevent them from showing the markers:
    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());
  • edited 4:14AM
    Thanks - I used the 2nd suggestion, in a fashion. I deconstructed the _render() method from Blog_base_controller and used it to my own ends, which seems the right way to do it - build up the layout inside out and then display.

    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!
  • edited 4:14AM
    Gumster, I love you. Thank you for having this discussion; I have had so many issues trying to incorporate Ion auth properly into Fuel as an advanced module, and this really helped me rethink how I was approaching it. Kudos to you!
  • edited 4:14AM
    Jfrei,

    I've used Ion auth a few times with Fuel. You might be interested in this hooks solution I used recently
Sign In or Register to comment.