PHP spl_autoload_register命名空间会干扰文件包含


PHP spl_autoload_register namespaces interfere with file includes

我不知道是否遗漏了什么,但使用名称空间似乎会破坏我的应用程序。它找不到父类,因为当自动加载寄存器被调用时,它在类名中包含了名称空间

spl_autoload_register(function($classname){
    if (preg_match('/[a-zA-Z]+Controller$/', $classname)) {
        echo __DIR__ . '/controllers/' . $classname.".php" . "<br />";
        require __DIR__ . '/controllers/' . $classname.".php";
    }
});
//echo produces:
/var/www/web/controllers/DefaultController.php
/var/www/web/controllers/Project'Controllers'BaseController.php

Project''Controllers是在默认控制器和基本控制器中都使用的命名空间。默认扩展基本控制器。

spl自动加载为什么要这样做?

结构:

web/控制器:

BaseController.php
DefaultController.php

基本控制器:

namespace Project'Controllers;
class BaseController
{
    private $config;
    public function __construct($config)
    {
        $this->config = $config;
    }
}

默认控制器:

<?php
namespace Project'Controllers;
class DefaultController extends BaseController
{
}

主要问题似乎是你的自动加载器不知道它所属的根命名空间。所以实际上你的自动加载程序应该知道或成为命名空间的一部分,所以在这种情况下是Project。

因此,您的自动加载需要做的第一件事是删除已知的根命名空间(当然,除非它被用作文件结构的一部分,而在本例中它不是)

<?php namespace Project;
// Within the namespace
$classname = ltrim(str_replace(__NAMESPACE__ . '''', '', $classname), '''');
// Outside of the namespace
$classname = ltrim(str_replace('Project''', '', $classname), '''');

现在是类名和实际文件位置。

// find the last backslash
if($last = strripos($classname, '''')) {
    $namespace = substr($classname, 0, $last); // Controllers
    $classname = substr($classname, $last+1); // DefaultController
}

现在,您可以将实际的文件位置构建到PHP类文件

$filepath = '/var/www/'; // Root
if(isset($namespace)) {
    // Add the controllers bit onto the root
    $filepath .= str_replace('''', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;
}
// add the class name (DefaultController) to the file path
$filepath .= str_replace('''', DIRECTORY_SEPARATOR, $classname) . '.php';

这应该会导致以下文件路径,如果存在,可以检查这些文件路径,然后如果存在,则包括这些文件路径。

/var/www/Controllers/BaseController.php

/var/www/Controllers/DefaultController.php