PHPActiverecord in CodeIgniter

March 31, 2012 | In: activerecord, orm, phpactiverecord

PHPActiverecord is the most ‘Agile’ (in my opinion) Object Relation Mapping (ORM) library for PHP and in that case we will use it with CodeIgniter.

First we need to download the source here.

In order for it to work with CodeIgniter, we need to do some hacking.

Lets create a folder named ‘phpactiverecord’ under $CI_PATH/application/libraries , where $CI_PATH is the folder where you extracted CI source.

$ mkdir application/libraries/phpactiverecord

Now, after we extract phpactiverecord, you can see sets of files like these below:

$ ls -l php-activerecord/
total 48
drwxr-xr-x  6 zeratool zeratool 4096 2011-10-22 15:56 ./
drwxr-xr-x 48 zeratool root   4096 2012-03-30 11:18 ../
-rw-r--r--  1 zeratool zeratool 1382 2011-10-22 15:56 ActiveRecord.php
-rw-r--r--  1 zeratool zeratool 1076 2011-10-22 15:56 CHANGELOG
drwxr-xr-x  4 zeratool zeratool 4096 2011-10-22 15:56 examples/
drwxr-xr-x  8 zeratool zeratool 4096 2011-10-22 15:56 .git/
-rw-r--r--  1 zeratool zeratool   52 2011-10-22 15:56 .gitignore
drwxr-xr-x  4 zeratool zeratool 4096 2011-10-22 15:56 lib/
-rw-r--r--  1 zeratool zeratool 1076 2011-10-22 15:56 LICENSE
-rwxr-xr-x  1 zeratool zeratool 5119 2011-10-22 15:56 README.md*
drwxr-xr-x  6 zeratool zeratool 4096 2012-01-03 08:56 test/

We only need ‘lib’ folder and the ‘ActiveRecord.php’ file :

$ cp -R php-activerecord/lib $CI_PATH/application/libraries/phpactiverecord
$ cp php-activerecord/ActiveRecord.php $CI_PATH/application/libraries/phpactiverecord

Next is we will create a library file called ‘ActiveRecord.php’ and put it under $CI_PATH/application/libraries

 $db_values) 
            {
            	// Convert to dsn format
            	$dsn[$name] = $db[$name]['dbdriver'] .
            		'://'   . $db[$name]['username'] .
            		':'     . $db[$name]['password'] .
            		'@'     . $db[$name]['hostname'] .
            		'/'     . $db[$name]['database'];
            }
        } 
        
        // Initialize ActiveRecord
        ActiveRecord\Config::initialize(function($cfg) use ($dsn, $active_group){
            $cfg->set_model_directory(APPPATH.'/models');
            $cfg->set_connections($dsn);
            $cfg->set_default_connection($active_group);
        });
        
    }
    
    
	/**
	 * Autoload
	 *
	 * Autoloads object classes that are used with DataMapper.
	 * This method will look in any model directories available to CI.
	 *
	 * Note:
	 * It is important that they are autoloaded as loading them manually with
	 * CodeIgniter's loader class will cause DataMapper's __get and __set functions
	 * to not function.
	 *
	 * @param	string $class Name of class to load.
	 */
	public static function autoload($class)
	{
		$CI =& get_instance();

		// Don't attempt to autoload CI_ , EE_, or custom prefixed classes
		if (in_array(substr($class, 0, 3), array('CI_', 'EE_')) OR strpos($class, $CI->config->item('subclass_prefix')) === 0)
		{
			return;
		}

		// Prepare class
		$class = strtolower($class);

		// Prepare path
		$paths = array();
		if (method_exists($CI->load, 'get_package_paths'))
		{
			// use CI 2.0 loader's model paths
			$paths = $CI->load->get_package_paths(false);
		}

		foreach (array_merge(array(APPPATH),$paths, self::$model_paths) as $path)
		{
			// Prepare file
			$file = $path . 'models/' . $class . EXT;

			// Check if file exists, require_once if it does
			if (file_exists($file))
			{
				require_once($file);
				break;
			}
		}

		// if class not loaded, do a recursive search of model paths for the class
		if (! class_exists($class))
		{
			foreach($paths as $path)
			{
				$found = self::recursive_require_once($class, $path . 'models');
				if($found)
				{
					break;
				}
			}
		}
	}

	/**
	 * Recursive Require Once
	 *
	 * Recursively searches the path for the class, require_once if found.
	 *
	 * @param	string $class Name of class to look for
	 * @param	string $path Current path to search
	 */
	protected static function recursive_require_once($class, $path)
	{
		$found = FALSE;
		if(is_dir($path))
		{
			$handle = opendir($path);
			if ($handle)
			{
				while (FALSE !== ($dir = readdir($handle)))
				{
					// If dir does not contain a dot
					if (strpos($dir, '.') === FALSE)
					{
						// Prepare recursive path
						$recursive_path = $path . '/' . $dir;

						// Prepare file
						$file = $recursive_path . '/' . $class . EXT;

						// Check if file exists, require_once if it does
						if (file_exists($file))
						{
							require_once($file);
							$found = TRUE;

							break;
						}
						else if (is_dir($recursive_path))
						{
							// Do a recursive search of the path for the class
							Activerecord::recursive_require_once($class, $recursive_path);
						}
					}
				}

				closedir($handle);
			}
		}
		return $found;
	}
}

// AutoLoad this
spl_autoload_register('Activerecord::autoload');

Some parts of the code above is derived from Matthew Machuga’s PHP-AR for CI Reactor
and from Datamapper ORM for CI

I just modify and joined them to simplify the integration.

And last but not the least, lets edit the CodeIgniter’s autoload file to well guess what , to autoload our ORM.
– $CI_PATH/application/config/autoload.php

$autoload['libraries'] = array('database', 'activerecord');

We need to autoload ‘database’ also to make it call the underlying database driver from CodeIgniter.

And that’s IT!

Comment Form