Location: PHPKode > scripts > ClassLoader > classloader/ClassLoader.class.php
<?php

/**
 * @package util
**/

/**
 * ClassLoader.
 * 
 * Provides a way of loading only the classes required by a given file in a Java-esque 'import' type way.
 * 
 * Usage is as follows:
 * 
 * <code>
 * ClassLoader::import('packageName.className'); 
 * </code>
 * 
 * @package	util
 * @version	0.1
 * @author	Alex Potsides, {@link http://www.achingbrain.net http://www.achingbrain.net}

 * @copyright	Alex Potsides, {@link http://www.achingbrain.net http://www.achingbrain.net}
 * @license	http://www.opensource.org/licenses/bsd-license.php BSD License
*/
class ClassLoader
	{
	public static $classPath = '/inc/packages/';
	private static $loadAttempts = 0;
	private static $loadedClasses = array();
	private static $loadedFiles = array();
	
	/**
	 * A private constructor so we cannot be instantiated
	 */
	private function __construct()
		{
		
		}
	
	/**
	 * Loads a class or package
	 * 
	 * @param	$className	string	package.className or package.*
	 */
	public static function import($className)
		{
		ClassLoader::$loadAttempts++;
	
		if(isset(ClassLoader::$loadedClasses[$className])) // have already tried to load this one
			{
			return;
			}
		
		// make sure we do not proccess a request for the requested class again
		ClassLoader::$loadedClasses[$className] = true;
		
		// look for * as last character to match 'packageName.*''
		if(substr($className, strlen($className) - 1) == '*')
			{
			ClassLoader::loadPackage($className);
			return;
			}
		
		$path = ClassLoader::getPath($className);
		$pathArr = explode('/', $path);
		$actualClassName = $pathArr[count($pathArr) -1];
		$path = substr($path, 0, strlen($path) - strlen($actualClassName));
		
		ClassLoader::getFileFromDirectory($path, false, $actualClassName);
		}
	
	/**
	 * Returns the number of classes that have been loaded
	 * 
	 * @return	int	The number of classes that have been loaded
	 */
	public static function getClassesLoaded()
		{
		return count(ClassLoader::$loadedFiles);
		}
	
	/**
	 * Returns the number of times classes have been loaded
	 * 
	 * @return	int	The number of times classes have been loaded
	 */
	public static function getLoadAttempts()
		{
		return ClassLoader::$loadAttempts;
		}
	
	/**
	 * Loads a whole directory of *.php files
	 */
	private static function loadPackage($packageName)
		{
		$path = ClassLoader::getPath(substr($packageName, 0, -1));
		ClassLoader::getFileFromDirectory($path);
		}
	
	/**
	 * Attempts to open a directory and either match the passed class name to a file name or load the whole lot
	 */
	private static function getFileFromDirectory($directoryPath, $multiple = true, $className = null)
		{
		try
			{
			$dir = new DirectoryIterator($directoryPath);
	
			foreach ($dir as $file)
				{
				$fileName = $dir->getFilename();
				
				/*
				 * If the class name is not null and the beginning of the file name matches the classname 
				 * - eg. to find DatabaseConnection.class.php or DatabaseConnection.interface.php
				 * 
				 * or
				 * 
				 * The class name is null and the last three letters of the file name are 'php'  - eg to find *.php
				 */
				if((!is_null($className) && (substr($fileName, 0, strlen($className)) == $className)) || (is_null($className)) && substr($fileName, strlen($fileName) - 3, 3) == 'php')
					{
					$filePath = $directoryPath . $fileName;
					
					if(!isset(ClassLoader::$loadedFiles[$filePath]))
						{
						/* add to the array first, otherwise the included file could request itself 
						 * - eg. if it tries to load all of its own package
						 */						
						ClassLoader::$loadedFiles[$filePath] = true;
						include($filePath);								
						}
					
					if($multiple === false) // in single file mode and we have our file, get out
						{
						return;
						}
					}
				}
			}
		catch(exception $e)
			{
			// need to do something better here			
			echo '<h1>Error loading class</h1><p>' . $e->getMessage() . '</p>';
			exit;
			}
		}
	
	/**
	 * Turns database.DatabaseConnection into database/DatabaseConnection, ready to have .class.php or whatever added to the end of it
	 */
	private static function getPath($path)
		{
		return $_SERVER['DOCUMENT_ROOT'] . ClassLoader::$classPath . str_replace('.', '/', $path);
		}
	}

?>
Return current item: ClassLoader