spl_autoload_register加载类两次

时间:2014-07-25 16:01:02

标签: php autoload spl-autoload-register

我一直试图通过这个非常简单的类加载器脚本来了解问题所在。 类加载器看起来像这样:

#src/vendors/Autoloading/lib/ClassLoader.php

namespace App\Vendors\Autoloading;

class ClassLoader
{
    private $path; 

    function __construct($path)
    {
        $this->path         = $path; 
    }

    public function load($class)
    {
      if(file_exists(  $class = str_replace(array('\\', '_'), DIRECTORY_SEPARATOR, $this->path) . '.php')){
            require $class;
            return true;
        }
    }

    public function register()
    {
        return spl_autoload_register([$this, 'load']);
    }
}

初始类加载器有更多方法和一些函数来验证文件名... 但是,在调试过程中,我不得不将其缩小到那个范围。

因此,autoload.php文件中需要该类加载器,如下所示。

#src/vendors/autoload.php

namespace App\Vendors;

require 'Autoloading/lib/ClassLoader.php';
$autoload = new Autoloading\ClassLoader('path/Foo/FooClass');
$autoload->register(); 

FooClass.php位于src/Foo/FooClass.php

namespace App\Foo;
class FooClass{}

并且自动加载部分实际上没有问题,类加载得很好,但它已经完成两次,它向我显示以下错误。我是从index.php文件中调用它

<?php 

use \App\Foo\FooClass;
FooClass::somefunction(); 

只是使用它会产生此错误。

  

致命错误:无法在第4行的/path/to/index.php中重新声明类路径\ foo \ FooClass

3 个答案:

答案 0 :(得分:2)

您的自动加载功能有误:

public function load($class)
{
    if (
        file_exists(  
            $class = str_replace(
                array('\\', '_'), 
                DIRECTORY_SEPARATOR, 
                $this->path)
            . '.php')
    ) {
        require $class;
        return true;
    }
}

该函数是calles,带有要加载的类的名称(如果不可能,该函数应该什么都不做)。

您所做的是忽略类名,并根据创建自动加载器的路径创建一个新名称。这将始终加载相同的文件,具有相同的类,即使有不同的类要加载。

这解释了为什么你得到错误,因为无论传递哪个类名,你总是要包含一个与路径相关的文件。

您可能想要使用合适的PSR-0或PSR-4自动加载器。我建议使用Composer附带的那个,因为你很可能迟早会使用Composer。为什么不从今天开始呢?

答案 1 :(得分:1)

尝试使用require_once代替require。您的自动加载器无法跟踪到目前为止已加载的文件。

这是我如何设置我的。我不上课。也许这会有所帮助

function PlatformAutoloader($classname) {
    try {
        // Change \ to / so namespacing will work
        $classname = strtolower(str_replace('\\', DIRECTORY_SEPARATOR, $classname));

        if(!@include_once(DIR_CLASSES . DIRECTORY_SEPARATOR . $classname . '.php')) return false;
    } catch(Exception $e) {
        return false;
    }
}
spl_autoload_register('PlatformAutoloader');

答案 2 :(得分:1)

在检查文件

之前,使用class_exists检查该类是否已存在