Fix UniversalClassLoader issues with leading slashes.

This fixes a bug in UniversalClassLoader when attempting to autoload class names with leading slashes:

    $namespacedClass = "\\Foo\\Bar";
    $pearlikeClass   = "\\Foo_Bar";

    $namespaced = new $namespacedClass();
    $pearlike   = new $pearlikeClass();

`UniversalClassLoader::loadClass()` was unable to load PEAR-like classes with leading slashes because it found the slash and assumed that the requested class was namespaced. It was unable to load namespaced classes with leading slashes because it would look them up in the autoloader's registered namespaces, and was unable to match '\Foo' to 'Foo'. One (ugly) workaround for the namespaced classes was to register all namespaces twice:

    $loader->registerNamespaces(array(
        'Foo'  => __DIR__ . '/lib',
        '\Foo' => __DIR__ . '/lib',
    ));

But that's not very pretty, nor does it solve the bug with PEAR-like classes. Stripping the leading slash before trying to autoload allows UniversalClassLoader to load both namespaced and PEAR-like classes.
This commit is contained in:
Justin Hileman 2010-10-19 15:45:04 -04:00 committed by Fabien Potencier
parent dd7e33af6b
commit 0ccc9805f5
6 changed files with 69 additions and 0 deletions

View File

@ -123,6 +123,10 @@ class UniversalClassLoader
*/
public function loadClass($class)
{
if ('\\' === $class[0]) {
$class = substr($class, 1);
}
if (false !== ($pos = strripos($class, '\\'))) {
// namespaced class name
$namespace = substr($class, 0, $pos);

View File

@ -0,0 +1,7 @@
<?php
namespace Namespaced;
class Bar {
public static $loaded = true;
}

View File

@ -0,0 +1,7 @@
<?php
namespace Namespaced;
class Foo {
public static $loaded = true;
}

View File

@ -0,0 +1,5 @@
<?php
class Pearlike_Bar {
public static $loaded = true;
}

View File

@ -0,0 +1,5 @@
<?php
class Pearlike_Foo {
public static $loaded = true;
}

View File

@ -0,0 +1,41 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Tests\Component\HttpFoundation;
use Symfony\Component\HttpFoundation\UniversalClassLoader;
class UniversalClassLoaderTest extends \PHPUnit_Framework_TestCase
{
/**
* @covers Symfony\Component\HttpFoundation\UniversalClassLoader::loadClass
* @dataProvider testClassProvider
*/
public function testLoadClass($className, $testClassName, $message)
{
$loader = new UniversalClassLoader();
$loader->registerNamespace('Namespaced', __DIR__ . DIRECTORY_SEPARATOR . 'Fixtures');
$loader->registerPrefix('Pearlike_', __DIR__ . DIRECTORY_SEPARATOR . 'Fixtures');
$loader->loadClass($testClassName);
$this->assertTrue(class_exists($className), $message);
}
public static function testClassProvider()
{
return array(
array('\\Namespaced\\Foo', 'Namespaced\\Foo', '->loadClass() loads Namespaced\Foo class'),
array('\\Pearlike_Foo', 'Pearlike_Foo', '->loadClass() loads Pearlike_Foo class'),
array('\\Namespaced\\Bar', '\\Namespaced\\Bar', '->loadClass() loads Namespaced\Bar class with a leading slash'),
array('\\Pearlike_Bar', '\\Pearlike_Bar', '->loadClass() loads Pearlike_Bar class with a leading slash'),
);
}
}