Skip to content
Create a gist now

Instantly share code, notes, and snippets.

Embed URL


Subversion checkout URL

You can clone with
Download ZIP
Add MIT license.
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license. For more information, see
* <>.
* SplClassLoader implementation that implements the technical interoperability
* standards for PHP 5.3 namespaces and class names.
* // Example which loads classes for the Doctrine Common package in the
* // Doctrine\Common namespace.
* $classLoader = new SplClassLoader('Doctrine\Common', '/path/to/doctrine');
* $classLoader->register();
* @license MIT License
* @author Jonathan H. Wage <>
* @author Roman S. Borschel <>
* @author Matthew Weier O'Phinney <>
* @author Kris Wallsmith <>
* @author Fabien Potencier <>
class SplClassLoader
private $_fileExtension = '.php';
private $_namespace;
private $_includePath;
private $_namespaceSeparator = '\\';
* Creates a new <tt>SplClassLoader</tt> that loads classes of the
* specified namespace.
* @param string $ns The namespace to use.
public function __construct($ns = null, $includePath = null)
$this->_namespace = $ns;
$this->_includePath = $includePath;
* 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;
* Gets the namespace seperator used by classes in the namespace of this class loader.
* @return void
public function getNamespaceSeparator()
return $this->_namespaceSeparator;
* Sets the base include path for all class files in the namespace of this class loader.
* @param string $includePath
public function setIncludePath($includePath)
$this->_includePath = $includePath;
* Gets the base include path for all class files in the namespace of this class loader.
* @return string $includePath
public function getIncludePath()
return $this->_includePath;
* Sets the file extension of class files in the namespace of this class loader.
* @param string $fileExtension
public function setFileExtension($fileExtension)
$this->_fileExtension = $fileExtension;
* Gets the file extension of class files in the namespace of this class loader.
* @return string $fileExtension
public function getFileExtension()
return $this->_fileExtension;
* Installs this class loader on the SPL autoload stack.
public function register()
spl_autoload_register(array($this, 'loadClass'));
* Uninstalls this class loader from the SPL autoloader stack.
public function unregister()
spl_autoload_unregister(array($this, 'loadClass'));
* Loads the given class or interface.
* @param string $className The name of the class to load.
* @return void
public function loadClass($className)
if (null === $this->_namespace || $this->_namespace.$this->_namespaceSeparator === substr($className, 0, strlen($this->_namespace.$this->_namespaceSeparator))) {
$fileName = '';
$namespace = '';
if (false !== ($lastNsPos = strripos($className, $this->_namespaceSeparator))) {
$namespace = substr($className, 0, $lastNsPos);
$className = substr($className, $lastNsPos + 1);
$fileName = str_replace($this->_namespaceSeparator, DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;
$fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . $this->_fileExtension;
require ($this->_includePath !== null ? $this->_includePath . DIRECTORY_SEPARATOR : '') . $fileName;

The link in the header comment is broken, the document is now located here:


Maybe it shouldn't use require but include in loadClass()? Or is there a reason to do that?


loadClass() method should be changed to return boolean result because current implementation breaks the logic of calling autoloaders in the stack. Here fix for that (PHP >=5.3.3):

$fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . $this->_fileExtension;
$filePath  = stream_resolve_include_path($fileName);
if ($filePath) {
    require $filePath;
return $filePath !== false;

How ridiculous. I put it on my blog in case the cache disappears.


I've created a gist (md) version of the proposal:


@jonahbron @Thinkscape @till @lisachenko @fuhrysteve Google Groups does not support pages.
The FIG released under a repository, reachable at:



@till Obviously for the reason that require throws a fatal error (E_COMPILE_ERROR), instead of a warning (E_WARNING) as include does.

bxt commented

@lessthanthree So? You want an E_COMPILE_ERROR from class_exists() calls? I would like to see lisachenko's comment realized. Or maybe another parameter if or not to throw exceptions and errors.


@bxt I usually want to halt the execution whenever a non existent file is imported, that's why I'd favor require over include. This gives me more control (or the illusion of...) over the application process flow. :)

bxt commented

@lessthanthree but you might want to pass to downstram autoloaders, and if a class is not found execution is stopped anyway. Maybe the best solution would be checking if the file exists and then requireing?


Here is my version for PSR-0 proposal It checks existence of the file and have two more features: relative paths and multiple include paths for single namespace. So you can configure loader like this:

$loader = new SplClassLoader('MyVendor', array('../vendor', '../src'));

Is anyone likely to actually need to change the namespace separator at runtime using those getters and setters? Perhaps I'm failing to understand what use-case that functionality is intended for, but wouldn't it be better to define that value as a constant instead?


@henry-smith Agree with you. Namespace separator is defined as a constant and definitely won't be changed.


@henry-smith and @lisachenko I think you guys are missing the point of the namespace separator. It's not there because you're going to change the namespace separator at runtime. That would be silly. Instead, it exists to support interoperability between different class naming conventions across vendor libraries in the same project.

For example, let's say you use a class from the original Zend Framework in your project. The ZF1 class naming convention uses underscores and looks like Zend_View_Helper. Meanwhile, in your PHP5.3+ awesomeness you utilize the more modern approach of namespacing your classes like mylib\AwesomeClass. The SplClassLoader is providing you a means to autoload both with the same underlying code (hence the name, Standard):

$myLibLoader = new SplClassLoader('mylib', '/path/to/mylib/src');

$zendLoader = new SplClassLoader('Zend', '/path/to/zend/lib');

Obviously, if you only utilize one namespace in your project and don't reference outside vendor libraries you'll never have need of this functionality.

As far as using require instead of include ...

At first I thought include might be better and that require was overkill. After all, you might not want script execution to die with a fatal E_ERROR if a file isn't found. But the more I considered it, I changed my mind.

First, the class loader is only invoked when a class that doesn't already exist is needed for script execution. Your script should die if you reference a class that doesn't exists and it can't be loaded. A missing class definition isn't something that should be handled. It's incumbent on the programmer to make sure these files make it in at runtime.

As for the argument that a downstream autoloader might exist to load a class not found (necessitating include over require) ... IMHO this would be a poor practice. The point of the SplClassLoader is to streamline autoloading of class files. There's no reason to waste resources invoking multiple autoloaders when the autoloader explicitly defines how class files should be named in the first place. One class loader per namespace is all that's needed; any more than that is unnecessary at best and terribly inefficient at worst.


Ah, nice clarification. I understand now, thanks. The docblock for setNamespaceSeparator() does kind of imply this too:

Sets the namespace separator used by classes in the namespace of this class loader.

The meaning of that would be absolutely clear to anyone who had that need as well. Kind of presumptuous of me to try to second guess a design decision just because I didn't understand it. Sorry about that!


@lisachenko (comment on July 12, 2011), why do you think that loadClass() must return boolean result?

PHP checks after each autoloader if class exists and if it's true it stop autoloaders queue. See


line 52
@return void

should be
@return string


Setters could return $this for method chaining. Powerful in 5.4

(new SplClassLoader())->setIncludePath(realpath(dirname(__FILE__) . '/lib'))

I was trying to load the Slim Framework like this:

$classLoader = new SplClassLoader('Slim', 'libs/Slim');

But I wasn't able to, I found the problem was the following in Line 123:

$this->_namespace.$this->_namespaceSeparator === substr($className, 0, strlen($this->_namespace.$this->_namespaceSeparator))

The problem is that the statement looks like Slim_ === Slim so it returns false, It works fine with namespaced classes though


If this class is to insist on require() instead of include & return false, and it's being held up as the gold standard by the authors of PSR, then surely for consistency they should deprecate the class_exists() function?

As has been noted by several people above, the autoloader is not called only when a class is needed; it is also called whenever a class' existence needs to be checked, particularly in frameworks and apps that use a plugin architecture. Autoloaders which ignore this are broken.


I must agree with @parsingphase. A stacked autoloader implementation with require() must only use require if it first checks with either file_exists() or is_readable().


you should use strtr (for a char replace) vs str_replace (more faster) ...


SRP principle : you have forget a resolveFileName($class) function, should not be defined in loadClass function ...


Wouldn't be better if the path matching with the class name was previously converted to lowercase?
That would resolve conflicts with Windows and would normalize the directory structure too:




Why does the constructor accept NULL value for both parameters? That makes no sense in my opinion.


This example doesn't follow PSR-2 coding style. I think PSR should refer to examples which follow PSR. There is at least one issue - private members prefixed with "_".


Isn't it a little strange use a construction like "if (false !== ($lastNsPos = strripos($className, $this->_namespaceSeparator)))[...]", with the false statement first? Looks like a little causative (like master yoda talks)


How about having a static class that do all the work for a generic autoloading

public static function autoRegister($ns = null, $includePath = null){
    $instance = new static($ns, $includePath);

The comment of @parsingphase is so true!
You have to use include instead of require for 3 reasons:

  • Usage of class_exists, interface_exists & trait_exists are broken
  • Spl autoloading stack may contain other type of loader to support different naming convention (like Pear), using require force the end user to put you loader at the bottom of the stack, else it broke everything
  • Using require will trigger a fatal error at line 133 of file SplClassLoader.php, WTF : how can I find where the missing or mispelled class is in my code, now?

Just in case you need a lightweight solution to autoload PSR-0 and Zend like libs, take a look at this gist.

It's extreme, it's not following PSR-1 / PSR-2 coding standards at all, but it's short, fun and effective :

    @include preg_replace('#\\\|_(?!.*\\\)#','/',$c).'.php';

Thanks for the useful autoloader!


This class should be updated to match the the PSR-2 standard


Very useful~


This is the way I do it. It only requires the file if its on the include path, so you get your error messages in the right place and multiple autoloaders can be used, like in @adriengibrat's comment.

spl_autoload_register(function($class) {
    $parts = explode('\\', $class);

    # Support for non-namespaced classes.
    $parts[] = str_replace('_', DIRECTORY_SEPARATOR, array_pop($parts));

    $path = implode(DIRECTORY_SEPARATOR, $parts);

    $file = stream_resolve_include_path($path.'.php');
    if($file !== false) {
        require $file;

Current implementation implicitly shows that there is only one include path possible for one Vendor Name

But let`s imagine I have the following structure of the code
folder1/Vendor Name 1/Namespace 1/...
folder2/Vendor Name 1/Namespace 1/..
folder2/Vendor Name 1/Namespace 2/...

There is no one rule from PSR-0 has conflict with this case:

  • A fully-qualified namespace and class must have the following structure <Vendor Name>()*
  • Each namespace must have a top-level namespace ("Vendor Name")
  • Each namespace can have as many sub-namespaces as it wishes.
  • etc...

You cannot have the same namespace in two folders, like your Vendor1. You might be lucky and have Subnamespaces below that Namespace1, and can then use this loader.

Otherwise, you'd have to solve the question of "how do you know where the file for a class is", and if the answer is "I start looking in folder1, and if nothing is found, continue with folder2", that might work, but is is not really PSR-0 compliant.

And it isn't feasible as well. What if the same class exists in both folders?


What do you think is it make sense to add this rule item into PSR-0 standards?
P.S. I guess here is an answer


I think "include" is more logical, after all the method class loader utilises to load a class should be encapsulated. No one needs to know about that, so using "file_exists" is the best.

If the class is not found with your class load the php will keep searching until it reaches the last class loader, you don't need to worry about boolean return either. A fatal error will be generated if PHP not found the class anyway. Don't forget that some libraries use their own class loaders and using "require" will break them.


pls add a licence ( LGPL / MIT / BSD / GPL / AGPL )


Am I missing something here (I'm a namespace noob)?

Using a namespaced class such as Zend\XmlRpc\Server.php (use Zend\XmlRpc) and stepping through the code, the function :

tryLoadClassByPath($className, $unresolvedFilePath) 

always returns false for namespaced classes because the $className parameter is the bare
class name without its namespace prefix so fails the test.

$isFound = class_exists($className, false);

If I modify the calling code to use the namespaced class like this:

public function loadClass($className)
        $originalClassName = $className;

... and use this later ...

                $isFound = $this->tryLoadClassByPath($originalClassName, $unresolvedFilePath);

then it returns true as expected. The class file is successfully loaded in any case as the file path is correctly setup so you don't actually see much happen even if the function does return false but I am fairly certain it should return true.


There was a problem with constants I'd defined. My BASE_PATH CONST was defined like this

define('BASE_PATH', dirname(realpath(__FILE__)) . '/');

So when I instantiated your class like this

$classLoader = new SplClassLoader('App\Controllers\Content', BASE_PATH);

The trailing Slash from my BASE_PATH Const was the causefor an error.
To modify this class by adding a rtrim() to the __construct method worked for me:

public function __construct($ns = null, $includePath = null)
    $this->_namespace = $ns;
    $this->_includePath = rtrim($includePath, '/');

Perhaps something for the next one needs trailing slashes :)


As ClemensSahs mentioned I would also like to know the license for this code.


Please remove the link in the file, it leads to a 404 page.


Zeokat very usefull piece of code. I need to know the license because i thinking into using it.


Hi All,

Why declared methods setIncludePath / getIncludePath and not declared methods getNamespace and setNamespace in this SplClassLoader ??



Download file of this gist don't have white line in the end file. See PSR2


This link

Is a fork to this file with the next PHPDoc fixes:

  • The constructor has two parameters, this was not reflected before.
  • The PHPDoc related to getNamespaceSeparator(), had a typo. It said 'seperator' instead of 'separator'.
  • The PHPDoc related to getNamespaceSeparator(), now has a return string instead of return void.

I think, there is a problem with this implementation or the PSR-0 itself. When - theoretically - using classnames that begin or end with and underscore "", e.g. \Vendor\Namespace_Class_Extension.php

This would end up in something like this:
Vendor/Namespace//Class/Extension/.php and will definitely fail to load.

There is no omission or MUST NOT for leading or trailing underscores in the definition of classnames.

To avoid this, just replace the line:


$fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . $this->_fileExtension;



$fileName .= preg_replace("#([a-z0-9]+)_([a-z0-9]+)#i", "$1" . DIRECTORY_SEPARATOR . "$2", $className) . $this->_fileExtension;

and the example above will end up in:



Maybe useful: - taken from PSR and little fixed like docs etc.
If need anything to change just PR.

Btw, consider using PSR4 autoloader:


Here is the file loading solution I use within my autoloader:
REM** $class can be a Class OR an Interface

include $filename;
// Check to see if the include declared the class
if(!class_exists( $class, FALSE )) {
// Check to see if the include declared the interface
if(!interface_exists( $class, FALSE )){
// We do not have the class nor interface : file did not load or did not exist
// Do something : Log error; check other file resources or die gracefully.

Why I use this:
Loading files is normally the slowest part of any php application. Using file_exists(), even though it does not load the file still takes 'almost' as much time as loading the file itself (assuming a small file which class files tend to be >10Kb). So if you use:

require fileName;

From a application run time perspective its like loading the file twice !!! In addition require will kill your app if it fails where include only throws a warning.

Testing if the class or interface exists after an include will give you options to try something else before YOU gracefully exit your application.

Hope this helps


Got it.


Maybe replace 'require' with 'require_once' in loadClass(...) method ?


Hi guys, I have trouble.
Using SplClassLoader loosing displaying of parse errors and it is really pain the ass to debug the code manually. I can only catch then with register_shutdown_function(). I have set error_reporting to E_ALL, I did almost everything to display them and nothing.

If I require the classes manually everything works as expected (any errors are displayed). Any suggestions?


get class in to on?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.