Part of the EllisLab Network
x
 
Create New Page
 View Previous Changes    ( Last updated by Lisa Wess )

Extending Database Drivers

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'.EXT);

            
// 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.EXT;

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

            
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:

$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 FALSE)
    
{
        
// 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
        
parent::database($params$return$active_record);
    

abase_Drivers