Alternative autoloader for PSR-0 proposal
Posted: Sun May 30, 2010 8:16 am
The code below is an alternative to SplClassLoader which loads the classes following the naming convention described in http://groups.google.com/group/php-stan ... l-proposal . I wrote it because I found out that the original autoloader implementation is quite slow for a bigger number of libraries (vendors). Instead of registering different autoloader instance for each class that forces us to perform lots of unnecessary string operation when matching class names, I have one instance for all the classes and the paths are kept in an array:
Sample use:
Code: Select all
<?php
/**
* Aggregate autoloader that implements the technical interoperability
* standards for PHP 5.3 namespaces and class names.
*
* http://groups.google.com/group/php-standards/web/final-proposal
*
* @author Tomasz Jędrzejewski <http://www.zyxist.com/en/>
*/
class AggregateAutoloader
{
/**
* The list of available libraries.
* @var array
*/
private $_libraries = array();
/**
* The loaded file extension
* @var string
*/
private $_fileExtension = '.php';
/**
* The namespace separator
* @var string
*/
private $_namespaceSeparator = '\\';
/**
* Registers a new library to match.
*
* @param string $library The library name to add.
* @param string $path The path to the library.
*/
public function addLibrary($library, $path)
{
if(isset($this->_libraries[(string)$library]))
{
throw new Exception('Library '.$library.' is already added.');
}
if($path[strlen($path) - 1] != DIRECTORY_SEPARATOR)
{
$path .= DIRECTORY_SEPARATOR;
}
$this->_libraries[(string)$library] = $path;
} // end addLibrary();
/**
* Checks if the specified library is available.
*
* @param string $library The library name to check.
*/
public function hasLibrary($library)
{
return isset($this->_libraries[(string)$library]);
} // end hasLibrary();
/**
* Removes a recognized library.
*
* @param string $library The library name to remove.
*/
public function removeLibrary($library)
{
if(!isset($this->_libraries[(string)$library]))
{
throw new Exception('Library '.$library.' is not available.');
}
unset($this->_libraries[(string)$library]);
} // end removeLibrary();
/**
* Sets the namespace separator used by classes in the namespace of this class loader.
*
* @param string $sep The separator to use.
*/
public function setNamespaceSeparator($sep)
{
$this->_namespaceSeparator = $sep;
} // end setNamespaceSeparator();
/**
* Gets the namespace seperator used by classes in the namespace of this class loader.
*
* @return string
*/
public function getNamespaceSeparator()
{
return $this->_namespaceSeparator;
} // end getNamespaceSeparator();
/**
* Sets the file extension of class files in the namespace of this class loader.
*
* @param string $fileExtension
*/
public function setFileExtension($fileExtension)
{
$this->_fileExtension = $fileExtension;
} // end setFileExtension();
/**
* Gets the file extension of class files in the namespace of this class loader.
*
* @return string $fileExtension
*/
public function getFileExtension()
{
return $this->_fileExtension;
} // end getFileExtension();
/**
* Installs this class loader on the SPL autoload stack.
*/
public function register()
{
spl_autoload_register(array($this, 'loadClass'));
} // end register();
/**
* Uninstalls this class loader from the SPL autoloader stack.
*/
public function unregister()
{
spl_autoload_unregister(array($this, 'loadClass'));
} // end unregister();
/**
* Loads the given class or interface.
*
* @param string $className The name of the class to load.
* @return void
*/
public function loadClass($className)
{
$replacement = str_replace(array('_', $this->_namespaceSeparator), DIRECTORY_SEPARATOR, ltrim($className, $this->_namespaceSeparator));
$id = strpos($replacement, DIRECTORY_SEPARATOR);
if($id === false)
{
return false;
}
$match = substr($replacement, 0, $id);
$path = substr($replacement, $id+1, strlen($replacement) - $id);
if(!isset($this->_libraries[$match]))
{
return false;
}
require($this->_libraries[$match].$path.$this->_fileExtension);
return true;
} // end loadClass();
} // end AggregateAutoloader;
Code: Select all
$loader = new AggregateAutoloader;
$loader->addLibrary('Foo', './path/to/Foo/');
$loader->addLibrary('Bar', './path/to/Bar/');
$loader->addLibrary('Joe', './path/to/Joe/');
$loader->register();