php命名空间自动加载目录


php namespace auto-load directory

我有一个类结构(树),如下所示:

- garcha/
|   - html/
|       Tag.php
|       VTag.php
|       etc..

工作原理:(由spl_autoload_register自动加载)

use garcha'html;
$tag = new html'Tag('a');

无法工作:

use garcha'html;
$tag = new Tag('a');

要实现它,不需要:(我不想逐行编写每个类文件的use语句,指向类目录并使用没有父命名空间的类)

use garcha'html'Tag;
use garcha'html'VTag;
... 

我不喜欢这种方式,因为它很无聊,需要更多的时间,不太灵活(你可以更改文件结构,类名等。

简而言之:我正在尝试自动加载命名空间类目录,并使用其中具有非限定名称的类。

自动加载器功能:

class AutoLoader 
{
    protected static $pathes = array();
    /**
     * add pathes
     * 
     * @param string $path
     */
    public static function addPath($path) 
    {
        $path = realpath($path);
        if ($path) 
        {
            self::$pathes[] = $path . DIRECTORY_SEPARATOR;
        }
    }
    /**
     * load the class
     * @param string $class
     * @return boolean
     */
    public static function load($class) 
    {
        $classPath = $class.'.php'; // Do whatever logic here
        foreach (self::$pathes as $path) 
        {
            if (is_file($path . $classPath)) 
            {
                require_once $path . $classPath;
                return true;
            }
        }
        return false;
    }
}

添加路径:

AutoLoader::addPath(BASE_PATH.DIRECTORY_SEPARATOR.'vendor');

自动加载工作,问题是如何处理

use garcha'html; // class directory

并且使用没有前导html 的类

$tag = new Tag('p'); // not $tag = new html'Tag('p');

您可以尝试不同的解决方案:

首先:您可以在pathes变量中添加garcha/html,如::addPath('garcha/html')

第二:尝试在自动加载器中使用以下代码

foreach (glob("garcha/*.php") as $filename)
{
    require_once $filename;
}

glob基本上会匹配所有以.php结尾的文件,然后您可以使用它们将它们添加到pathes变量中,或者只包含它们。

注意:您需要稍微修改您的自动加载器才能在其中使用上述循环。

编辑:试试这个:

public static function load($class) 
{
    // check if given class is directory
    if (is_dir($class)) {
       // if given class is directory, load all php files under it
       foreach(glob($class . '/*.php') as $filePath) {
          if (is_file($filePath)) 
          {
             require_once $filePath;
             return true;
          }
       }
    } else {
       // otherwise load individual files (your current code)
       /* Your current code to load individual class */
    }
    return false;
}