Welcome Guest, Not a member yet? Register   Sign In
Is there a good way to work with more extended controller parent classes then just MY_Controller.php?
#1

[eluser]Jelmer[/eluser]
I'm kinda hoping I haven't missed something that I should have known for a long time by now, but here's the "problem": I need more extended controller classes then just the MY_Controller.php class. For instance I recently wrote a basic extention for the controller class that allows for easy creation of "wizards" that checks whether all pages of the wizard have been filled out up to the point you're requesting and auto loads correctly named views.

Of course I could put most of this functionality in a library and call that library from my various wizards but I prefer to have these "Wizard Controller" types where I only have to specify the fields, create the views and create a saving function and all other work is done by the parent functions.
I can't use MY_Controller because I certainly don't want all these options in all my controllers.

I've solved this problem right now like this (where MP_Wizard of course already extends the Controller class):
Code:
<?php

require(APPPATH.'libraries/MP_Wizard.php');

class Install extends MP_Wizard {
    // etc...
}

So the basic question is: is there a better way of doing this?

(Ps. for those interested: I'll probably release the MP_Wizard parent class, but right now I don't have the time to write documentation and remove my application specific code)

Edit: like other times, I started thinking in other directions after explaining my problem. While I still don't think there's a native CI way, an autoloader might provide a more elegant solution.

Edit 2: my final solution is in post #4.
#2

[eluser]Jelmer[/eluser]
Still an ugly fix but it does at least rid my controllers from the "require" line.

I added an autoloader to the main index.php which is only functional before the Controller is initiated by CI, after that my MY_Router.php specifies a new autoloader:
Code:
function __autoload($class)
{
    if (preg_match('/^([a-z0-9_]+)$/i', $class))
        @include_once(APPPATH.'libraries/'.$class.'.php');
}

Edit: I ended up changing this, check my final solution in post #4.
#3

[eluser]adamp1[/eluser]
I had the same requirement. I did it the first way with the require. The issue with the second is your going to be loading all libraries which is a big overhead possibly on every page.
#4

[eluser]Jelmer[/eluser]
Quote:The issue with the second is your going to be loading all libraries which is a big overhead possibly on every page.
I'm not sure what you mean by this? The __autoload function is only called when a class is unknown in the current process and shouldn't be called more then once (unless there's another unknown class called with new, extends or class:Smile.
Or am I getting this wrong? As far as I know it should effectively cause just the one extra call on include and thus have the same amount of loading.
#5

[eluser]Jelmer[/eluser]
For anyone interested and also needing functionality like I described above. I ended up looking to others for cues, specificly took some from the basic RapidDataMapper autoloader I was already using and by studying PyroCMS (thanks Phil & co. Wink).

The better solution wasn't in changing the index.php, but in moving the autoloader from the Loader class to the Router class. As the Router is loaded as one of the first CI core libraries it will allow autoloading of Abstract classes you're extending or Interfaces you're implementing in your controlles, libraries or models.

Here below is my extended MY_Router.php that allows for this kind of autoloading. It's explained well enough in the comments I think:
Code:
<?php

class MY_Router extends CI_Router
{
    public function __construct()
    {
        parent::CI_Router();
        
        // register the autoloader
        spl_autoload_register(array('MY_Router', '__autoloader'));
    }

    /**
     * Autoloader for libraries, abstracts, interfaces and RapidDataMapper data objects
     *
     * @param  string
     * @return void
     */
    public static function __autoloader($class)
    {
        // For security reasons only allow alphanumeric chars and underscores
        $class = preg_replace('/([^a-zA-Z0-9_]*)/', '', $class);

        // Don't autoload CI_ or MY_ prefixed classes, leave that to CI
        if (substr($class, 0, 3) == 'CI_' || substr($class, 0, 3) == 'MY_' || $class == 'Model')
            return;
        // Loader for RapidDataMapper data models
        if (file_exists(APPPATH . 'data_model/'.strtolower($class).EXT))
        {
            require(APPPATH . 'data_model/'.strtolower($class).EXT);
            return;
        }
        // Loader for Abstract classes (always prefixed with "Ab_")
        elseif (substr($class, 0, 3) == 'Ab_' && file_exists(APPPATH.'libraries/Abstracts/'.$class.EXT))
        {
            require(APPPATH.'libraries/Abstracts/'.$class.EXT);
            return;
        }
        // Loader for Interfaces (always prefixed with "Int_")
        elseif (substr($class, 0, 4) == 'Int_' && file_exists(APPPATH.'libraries/Interfaces/'.$class.EXT))
        {
            require(APPPATH.'libraries/Interfaces/'.$class.EXT);
            return;
        }
        // Loader for normal libraries
        elseif (file_exists(APPPATH.'libraries/'.$class.EXT))
        {
            require(APPPATH.'libraries/'.$class.EXT);
            return;
        }
        // Loader for non-CI specific libraries (like SimplePie)
        elseif (file_exists(APPPATH.'libraries/Third_party/'.$class.EXT))
        {
            require(APPPATH.'libraries/Third_party/'.$class.EXT);
            return;
        }
    }

    // ------------------------------------------------------------------------
}


/* End of file MY_Router.php */
/* Location: ./application/libraries/MY_Router.php */




Theme © iAndrew 2016 - Forum software by © MyBB