无法通过 spl_autoload_register 加载具有命名空间的 PHP 类?

标签 php namespaces autoloader spl-autoload-register

当在类中实现 namespace 时,我在使用 spl_autoload_register 加载类时遇到问题。

下面的 autoloader 类,但是当使用 no 命名空间时我加载任何类都没有问题,

class autoloader
{
    /**
     * Set the property.
     */
    public $directory;
    public $recursive;

    /**
     * Receive the supplied data.
     * @string $directory
     * @array $recursive default: models
     */
    public function __construct($directory, $recursive = array('search' => 'models') ) 
    {
        # Store the data into the property.
        $this->directory = $directory;
        $this->recursive = $recursive;

        # When using spl_autoload_register() with class methods, it might seem that it can use only public methods, though it can use private/protected methods as well, if registered from inside the class:
        spl_autoload_register(array($this,'get_class'));

    }

    private function get_class($class_name)
    {
        # List all the class directories in the array.
        if ($this->recursive)
        {
            $array_directories =  self::get_recursive_directory($this->directory);
        }
        else
        {
            if (is_array($this->directory)) $array_directories =  $this->directory;
            else $array_directories =  array($this->directory);
        }

        # Set the class file name.
        $file_name = 'class_'.strtolower($class_name).'.php';

        # Loop the array.
        foreach($array_directories as $path_directory)
        {
            if(file_exists($path_directory.$file_name)) 
            {
                # There is no need to use include/require_once. Autoload is a fallback when the system can't find the class you are instantiating. 
                # If you've already included it once via an autoload then the system knows about it and won't run your autoload method again anyway. 
                # So, just use the regular include/require - they are faster.
                include $path_directory.$file_name;
            } 
        }

    }

    # However the memory consumption of this can be huge if you have a very large directory tree with only a few matches.
    # @source: http://stackoverflow.com/questions/9294543/search-and-list-specific-directories-only
    public function get_recursive_directory($directory)
    {
        # Create an object that allows us to iterate directories recursively.
        # Stolen from here: 
        # http://www.php.net/manual/en/class.recursivedirectoryiterator.php#102587
        $iterator = new RecursiveIteratorIterator
                    (
                        new RecursiveDirectoryIterator($directory),
                        RecursiveIteratorIterator::CHILD_FIRST
                    );

        # This will hold the result.
        $result = array();

        # Loop the directory contents.
        foreach ($iterator as $path) 
        {

            # If object is a directory and matches the search term ('models')...
            if ($path->isDir() && $path->getBasename() === $this->recursive['search']) 
            {

                # Add it to the result array.
                # Must replace the slash in the class - dunno why!
                $result[] = str_replace('\\', '/', $path).'/';
                //$result[] = (string) $path . '/';

            }

        }

        # Return the result in an array.
        return $result;
    }
}

例如一个标签类,

namespace hello;

class tag extends \core
{
}

现在通过 autoloader 类加载类,

# Autoload the classes from the specific folder.
$autoloader = new autoloader("C:/wamp/www/website/local/applications/master/sides/models/", $recursive = false);

# Instantiate the tag.
$tag = new hello\tag($connection);

结果,

Fatal error: Class 'hello\tag' not found in C:\wamp\www\website\local\applications\master\sides\views\tags.php on line 7

知道如何修复我的 autoloader 类,以便无论是否有命名空间我都可以加载这些类吗?

编辑:

我保存类和类命名的文件夹,

C:\wamp\www\website\local\applications\master\sides\models\

class_tag.php
class_something.php

最佳答案

您的错误出在您的 get_class() 方法中。 $class_name 包含完全限定的类名及其命名空间。在您的情况下,您必须从类名中删除命名空间。

$file_name = 'class_'.strtolower(array_pop(explode('\\', $class_name))).'.php';

我强烈推荐使用 PSR-0自动加载标准。如果您将使用任何库,它们很可能使用相同的标准,而您只有一个自动加载器。

关于无法通过 spl_autoload_register 加载具有命名空间的 PHP 类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13752256/

相关文章:

php - 让客户端与服务器上的进程通信

javascript - 是否可以使用php命令更新js文件?

php - 通过 Android 应用程序验证 Paypal 电子邮件地址

php - 中未找到自动加载 PSR-4 命名空间接口(interface)

namespaces - 为什么 Eclipse CDT 在关闭命名空间大括号后不添加注释?

python - 覆盖父命名空间变量

php - 不能对自动加载器使用命名空间

ruby-on-rails - Rails 4.1 无法自动加载命名空间类

php - ZF2 : autoloading libraries without namespaces

javascript - 根据数字类名称定位 div