Skip to content

Extending Database Drivers

Mohamed YOUNES edited this page Nov 19, 2015 · 36 revisions

Category:Help | Category:Help::TipsAndTricks | Category:Help::Databases

Much complaints about not being able to extend the CI database class. In the docs it says this can't be done, but here is a simple solution that fits it all! Don't believe it?, well read on..

The solution comes in 3 simple steps:

1) Extend your loader class by creating the file MY_Loader.php. Put it into your libraries directory in the application path (or if you are using CI 2.x.x then put it into application\core\ path):

<?php

class MY_Loader extends CI_Loader {

}
      
?>

2) Add the following function to your MY_Loader class:

     /**
     * Database Loader
     *
     * @access    public
     * @param    string    the DB credentials
     * @param    bool    whether to return the DB object
     * @param    bool    whether to enable active record (this allows us to override the config setting)
     * @return    object
     */
    function database($params = '', $return = FALSE, $active_record = FALSE)
    {
            // Do we even need to load the database class?
            if (class_exists('CI_DB') AND $return == FALSE AND $active_record == FALSE)
            {
            return FALSE;
            }

            require_once(BASEPATH.'database/DB'.'.php');

            // Load the DB class
            $db =& DB($params, $active_record);

            $my_driver = config_item('subclass_prefix').'DB_'.$db->dbdriver.'_driver';
            $my_driver_file = APPPATH.'libraries/'.$my_driver.'php';

            if (file_exists($my_driver_file))
            {
                require_once($my_driver_file);
                $db_obj = new $my_driver(get_object_vars($db));
                $db=& $db_obj;

                
            }

            if ($return === TRUE)
            {
                return $db;
            }
            // Grab the super object
            $CI =& get_instance();

            // Initialize the db variable.  Needed to prevent
            // reference errors with some configurations
            $CI->db = '';
            $CI->db = $db;
            // Assign the DB object to any existing models
            $this->_ci_assign_to_models();
    }

Please note if you are using CI 2.x.x then you need to comment out the last statement:-

// $this->_ci_assign_to_models();

3) Create your Database driver extension class, that you name MY_DB_mysql_driver.php (or substitute the mysql part for whatever driver you use - do that also for the classnames in the code below!). Put this file also in your applications libraries directory:

<?php
class MY_DB_mysql_driver extends CI_DB_mysql_driver {

  function __construct($params){
    parent::__construct($params);
    log_message('debug', 'Extended DB driver class instantiated!');
  }
  
  function get_first($table){
     return $this->limit(1)->get($table);
  }

}
?>

Congrats, now you can use your own db functions! Eg. get_first($table), the sample function from above, now fetches the first entry from your table:```php $this->db->get_first('sometable');

Other Example Functions

(put them also in your Extended DB driver class)

    /**
    * nests like, where statements
    * order in select clause is WHERE - LIKE
    * so WHERE a=0 OR ((WHERE b=0 AND c LIKE '%me%') OR m LIKE '%us') AND f LIKE '%nobody%
    * is possible
    */
    function nest($kind, $start, $end, $kind2=false){
        $kind = 'ar_'.$kind;
        $this->{$kind}[$start-1] = preg_replace('/(^AND )|(^OR )|^/', "$1$2(", $this->{$kind}[$start-1]);
        if($kind2){
            $kind = 'ar_'.$kind2;
        }
        $this->{$kind}[$end-1] .= ')';
        return $this;
    }

      /**
      * a limit function that takes an array or an integer,
      * so you only need one argument ever
      */
      function ulimit($limit){
       if($limit){
            if(is_array($limit)){
                $this->limit($limit[0], $limit[1]);
            }else{
                $this->limit($limit);
            }
        }
        return $this;
      }

Extending DB_Cache functionality

You can use the same trick to extend the functionality of the DB_Cache library. Copy the DB_Cache.php file from the system/libraries directory to your APPPATH/libraries directory. Then add this to your MY_Loader library:

    /**
     * Database Loader extension, to load our version of the caching engine
     *
     * @access    public
     * @param    string    the DB credentials
     * @param    bool    whether to return the DB object
     * @param    bool    whether to enable active record (this allows us to override the config setting)
     * @return    object
     */
    function database($params = '', $return = FALSE, $active_record = NULL)
    {
        // load our version of the CI_DB_Cache class. The database library checks
        // if this class is already loaded before instantiating it. Loading it now
        // makes sure our version is used when a controller enables query caching
        if ( ! class_exists('CI_DB_Cache'))
        {
            @include(APPPATH.'libraries/DB_cache'.EXT);
        }

        // call the parent method to retain the CI functionality
        return parent::database($params, $return, $active_record);
    }
Clone this wiki locally