我一直试图通过这个非常简单的类加载器脚本来了解问题所在。 类加载器看起来像这样:
#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
答案 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检查该类是否已存在