Codeigniter Drivers Tutorial

Codeigniter 2 has just keeps getting better. I’ve been having a play around with the new “Drivers” library that comes with Codeigniter 2 and it really has impressed me so much that I’ve started converting all my libraries into “Drivers”.

Ok what are Drivers

Drivers are a special type of Library that has a parent class and any number of potential child classes. Child classes have access to the parent class, but not their siblings. Drivers provide an elegant syntax in your controllers for libraries that benefit from or require being broken down into discrete classes.

Drivers are found in the system/libraries folder, in their own folder which is identically named to the parent library class. Also inside that folder is a sub folder named drivers, which contains all of the possible child class files.

In Basic English they are a collection of PHP Classes under one directory which aware of each other.

So lets build a driver called Honey.

Note the convention of using Capitals.

Create a folder called Honey

..application/libraries/Honey

Add your master class

..application/libraries/Honey/Honey.php

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Honey extends CI_Driver_Library {

    public $valid_drivers;
    public $CI;

    function __construct()
    {
        $this->CI =& get_instance();
    }

}

You’ll notice that this master class extends CI_Driver_Library.

you must have the variable $valid_drivers. This tells Codigniter which sub-classes to load. We don’t have any at the moment but we’ll be building them later.

We’ve made our $CI variable an instance of the codeigniter object by reference.  Anything you make public or protected in this master class will be available to all the sub-classes.

One of the great things about using the Driver Library is you can build all you logic here but use either a database or config file to get variable data which makes this such a sweet drop in application.

so for this example I’m going to use a config file for this application’s setting.

..application/config/honey.php

<?php

$config['modules'] = array('honey_queenbee', 'honey_workerbee');

 

I’ve called them modules but you can call them anything you like. Lets initialize them.

..application/libraries/Honey/Honey.php

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Honey extends CI_Driver_Library {

    public $valid_drivers;
    public $CI;

    function __construct()
    {
        $this->CI =& get_instance();
        $this->CI->config->load('honey', TRUE);
        $this->valid_drivers = $this->CI->config->item('modules', 'honey');
    }

}

 

Firstly we’re using Codeigniter to load our config file – see the user guide for details. I’m using the TRUE param so as to avoid name collision.

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Honey extends CI_Driver_Library {

    public $valid_drivers;
    public $CI;

    function __construct()
    {
        $this->CI =& get_instance();
        $this->CI->config->load('honey', TRUE);
        $this->valid_drivers = $this->CI->config->item('modules', 'honey');
    }

}

You don’t have to use a config file, you could just as easily use a database or hardcode into the class (although hard coding into the class makes it hard to port from one app to another). This needs to be an array.

Now for the two sub-classes. You must create a new folder called drivers. Note the naming convention.

..application/libraries/Honey/drivers

..application/libraries/Honey/drivers/Honey_queenbee.php

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Honey_queenbee extends CI_Driver {

    function pardon()

    {

        return 'You are forgiven';

    }

}

Note that this sub-class extends CI_Driver NOT CI_Driver_Library.

I’ve created an example function here that just returns a string but you can easily now run a db query using the $this->CI.

..application/libraries/Honey/drivers/Honey_workerbee.php

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Honey_workerbee extends CI_Driver {

    function busybee()

    {

        return $this->_pot_honey();

    }

    function _pot_honey()

    {

        return 'Here is a pot of honey';

    }

}

The Honey_workerbee class has two function, just for example sake.

Here is our controller

..application/controller/site.php

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Site extends CI_Controller {

    private $data = array();

    function __construct()
    {

        parent::__construct();

    }

    function call_honey()

    {

        $this->load->driver('honey');

        print $this->honey->queenbee('pardon');

    }

}

I’m only printing to the screen for demo purposes;

You can see that we are calling a method directly from a sub-class

But it would be much better to use our master class to control these calls as it has access to all the sub classes.

..application/controller/site.php

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Site extends CI_Controller {

    private $data = array();

    function __construct()
    {

        parent::__construct();

    }

    function call_honey()

    {

        $this->load->driver('honey');

        print $this->honey->naughty_bee();

    }

}

..application/libraries/Honey/Honey.php

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Honey extends CI_Driver_Library {

    public $valid_drivers;
    public $CI;

    function __construct()
    {
        $this->CI =& get_instance();
        $this->CI->config->load('honey', TRUE);
        $this->valid_drivers = $this->CI->config->item('modules', 'honey');
    }

    function naughty_bee()
    {
        return $this->queenbee->pardon();
    }
}

We’ve added a new method in the master class that calls the queenbee for a pardon.

Master Class can talk to all of the sub-classes. Sub-classes can talk to the master class. Sub classes cannot talk to each other. They must go through the master class.

..application/controller/site.php

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Site extends CI_Controller {

    private $data = array();

    function __construct()
    {

        parent::__construct();

    }

    function naughty()

    {

        $this->load->driver('honey');

        print $this->honey->naughty_bee();

    }

    function get_honey()
    {

        $this->load->driver('honey');
        $money = 10;
        if($this->honey->buy_honey($money)
        {
            print "eat the honey";
        }
        else
        {
            print "I do not have enough money";
        }
}

..application/libraries/Honey/Honey.php

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Honey extends CI_Driver_Library {

    public $valid_drivers;
    public $CI;

    function __construct()
    {
        $this->CI =& get_instance();
        $this->CI->config->load('honey', TRUE);
        $this->valid_drivers = $this->CI->config->item('modules', 'honey');
    }

    function naughty_bee()
    {
        return $this->queenbee->pardon();
    }

    function buy_honey($money = 0)
    {
        if($this->workerbee->busybee($money))
        {
            return TRUE;
        }
    }
}

A call to the master class which then calls the sub class

..application/libraries/Honey/drivers/Honey_workerbee.php

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Honey_workerbee extends CI_Driver {

    function busybee($money)

    {
 if($this->check_money($money)
 { return $this->_pot_honey();
 }

    }

    function _pot_honey()

    {

        return 'Here is a pot of honey';

    }

}

The worker bee can only sell the honey if the money is right.  The queen bee needs to check the money but we can’t go directly to the queen bee we must go through the master controller.

A little over the top I know but is shows what we can do.

..application/libraries/Honey/Honey.php

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Honey extends CI_Driver_Library {

    public $valid_drivers;
    public $CI;

    function __construct()
    {
        $this->CI =& get_instance();
        $this->CI->config->load('honey', TRUE);
        $this->valid_drivers = $this->CI->config->item('modules', 'honey');
    }

    function naughty_bee()
    {
        return $this->queenbee->pardon();
    }

    function buy_honey($money = 0)
    {
        if($this->workerbee->busybee($money))
        {
            return TRUE;
        }
    }

    function check_money($money)
    {
        return $this->queenbee->can_we_sell($money);
    }
}

..application/libraries/Honey/drivers/Honey_queenbee.php

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Honey_queenbee extends CI_Driver {

    function pardon()

    {

        return 'You are forgiven';

    }

    function can_we_sell($money)

    {

        if($money > 5)

        {

            return TRUE;

        }

    }
}

This should now return TRUE back to the controller.

The value is hard coded which is not good.  Lets improve that by adding the value to the config file.

..application/libraries/Honey/drivers/Honey_queenbee.php

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Honey_queenbee extends CI_Driver {

    function pardon()

    {

        return 'You are forgiven';

    }

    function can_we_sell($money)

    {

        if($money > $this->config->item('honey_pot_value', 'honey');

        {

            return TRUE;

        }

    }
}

..application/config/honey.php

<?php

$config['modules'] = array('honey_queenbee', 'honey_workerbee');
$config['honey_pot_value'] = 5;

A very simple example but you can see how we can make very useful apps that can easily be dropped into new projects.

2 thoughts on “Codeigniter Drivers Tutorial”

  1. Thanks for that tutorial. But how can I use the CI instance in a CI_Driver class e.g. when I wanted to use $this->CI->db->query(); I tried everything like in the constructor $this->CI &= get_instance(); or parent::$this->CI etc. do you have any suggestions?

    In your example I want to use the db instance in the function Honey_queenbee::pardon() extended by CI_Driver.

    Thanks a lot.

    Best Regards
    Pete

    1. The reference to CI has already been made in the honey class, which is public and therefore available to all the drivers (Sub Classes).

      So $this->CI->db->query(“THE QUERY”);

      Will work.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>