Skip to content

Instantly share code, notes, and snippets.

@jwage
Last active February 27, 2024 16:37
Star You must be signed in to star a gist
Save jwage/221634 to your computer and use it in GitHub Desktop.
Add MIT license.
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
/**
* SplClassLoader implementation that implements the technical interoperability
* standards for PHP 5.3 namespaces and class names.
*
* http://groups.google.com/group/php-standards/web/psr-0-final-proposal?pli=1
*
* // 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 http://www.opensource.org/licenses/mit-license.html MIT License
* @author Jonathan H. Wage <jonwage@gmail.com>
* @author Roman S. Borschel <roman@code-factory.org>
* @author Matthew Weier O'Phinney <matthew@zend.com>
* @author Kris Wallsmith <kris.wallsmith@gmail.com>
* @author Fabien Potencier <fabien.potencier@symfony-project.org>
*/
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;
}
}
}
@donghongya2011
Copy link

Got it.

@roquie
Copy link

roquie commented Feb 4, 2015

Maybe replace 'require' with 'require_once' in loadClass(...) method ?
http://php.net/manual/en/function.require-once.php

@mlefterov
Copy link

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?

@v3u3i87
Copy link

v3u3i87 commented Apr 16, 2015

get class in to on?

@ghorpade-naveen
Copy link

SplClassLoader line 133 is throwing error. File not found. But the file is present in another folder, how to fix this

@Romanzo
Copy link

Romanzo commented Jan 8, 2016

@klaussantana
Copy link

klaussantana commented Oct 4, 2016

Hello there people! New important info forgotten here..

The method loadClass on line 141 must return a boolean value! Recomended:

return class_exists($className, false) || trait_exists($className, false) || interface_exists($className, false);

This is imperative! PHP SPL autoload function suports bubbling effect.. You can register as many autoload functions as necessary, so, you must return a boolean value to indicate if the function loaded the resource or not. If it returns true, the SPL stops casting autoload functions.. if it returns false it keeps goin on the rest of the functions registered through spl_autoload_register.

The second parameter in every *_exists methods refer to autoloading and it must be false inside the autoload function scope to avoid infinite loop (the autoload function casting itself). If you try to load an interface, class_exists will drop false, because it's not a class, but interface_exists will drop true, then the autoload stops trying to load that resource.

Also, it's recommended to use include_once than any of other options. For instance, if you try to load My\Personal\Class\Name and My_Personal_Class_Name as the code is it will drop a fatal error trying to duplicate the resource (class, trait or interface). The fix proposed here will solve this problem.

See ya!

@GraniteConsultingReviews

I am trying this code from last 5 hours and it dint work.

@d4rkne55
Copy link

d4rkne55 commented Jul 5, 2018

Can someone remove the spam comments from 2017 (since first-reviews' comment)? I don't see any possibility to flag them from my side..

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment