基于目录结构的自动加载名称空间

时间:2015-06-01 09:08:37

标签: php autoload autoloader spl-autoload-register

根据PHP页面上的热门评论 spl_autoload_register( )

  

对于具有命名空间类的PHP 5.3用户来说是个好消息:

     

当您创建与>包含类的名称空间匹配的子文件夹结构时,您甚至不必定义自动加载器。

<?php
    spl_autoload_extensions(".php"); // comma-separated list
    spl_autoload_register();
?>

但是,当我有以下结构时:

* classes/someclass.php

* index.php

someclass.php包含以下内容:

<?php
    class someclass {
        function __construct( ) {
            echo 'It works!';
        }
    }
?>

index.php包含:

<?php
    spl_autoload_extensions(".php");
    spl_autoload_register();

    new classes\someclass;
?>

然后我收到以下错误:

  

致命错误:spl_autoload():类class \ someclass不可能   装载

我错了吗?我怎样才能做到这一点?

来自评论

这对班级来说都不起作用:

<?php
    namespace classes;
    class someclass {
        function __construct( ) {
            echo 'It works!';
        }
    }
?>

5 个答案:

答案 0 :(得分:5)

在someclass.php文件中,您必须在开始时定义命名空间。

<?php 
namespace classes;

答案 1 :(得分:5)

TLDR;它有效,但是:

    namespace classes; 中缺少
  • classes/someclass.php set_include_path(__DIR__);
  • 中缺少
  • index.php
  • spl_autoload_extensions(".php")不是必需的)

包含路径

SPL autoload implementation包含基于路径。使用点作为包含路径是相对于工作目录(!),它独立于脚本文件位置。 __DIR__命名classes文件夹位于index.php文件旁边所需的确切目录。

目录分隔符映射

接下来,自动加载器实现会在Unix系统上正确映射类命名空间分隔符。如果在o / p中丢失,the PHP source code clearly has this

文件名的大小写敏感度

源代码还显示了file-names to load are made lowercase。也就是说,如果您的文件系统区分大小写,则文件和目录名称必须为小写。

Refernces:

答案 2 :(得分:2)

由于修改了提示,发布了您引用的SedaSoft的用户Good news comment随后发布了another comment

  

我之前在此处所说的仅适用于Windows。内置   您致电时注册的默认自动加载器   没有任何参数的spl_autoload_register()只是添加了   限定的类名称加上每个的注册文件扩展名(.php)   包含路径并尝试包含该文件。

     

示例(在Windows上):

     

包含路径:

- "."
- "d:/projects/phplib"
     

要加载的限定类名:

network\http\rest\Resource
     

以下是发生的事情:

     

PHP尝试加载

'.\\network\\http\\rest\\Resource.php'
-> file not found
     

PHP尝试加载

'd:/projects/phplib\\network\\http\\rest\\Resource.php'
-> file found and included
     

请注意文件路径中的斜杠和反斜杠。在Windows上   效果很好,但在Linux机器上,反斜杠不起作用   此外,文件名区分大小写。

     

这就是为什么在Linux上快速简便的方法就是转换它们   限定的类名称为斜杠和小写并将它们传递给   像这样的内置自动加载器:

<?php
spl_autoload_register(
  function ($pClassName) {
    spl_autoload(strtolower(str_replace("\\", "/", $pClassName)));
  }
);
?>
     

但这意味着,您必须使用小写文件保存所有类   名。否则,如果省略strtolower调用,则必须使用   完全由文件名指定的类名,可以是   对于用非直截了当定义的类名来说很烦人   案例如e。 G。 XMLHttpRequest

     

我更喜欢小写的方法,因为它更容易使用和   文件名转换可以在部署时自动完成。

请注意,这位评论者实际上今天在SO上发布了一个答案,其中包含上述链接(以及简短的解释),但随后在review queue中被删除 - 可能是因为它的简洁。我已经恢复了评论者的回答以及链接的内容。他们的答案如下:

  

前一段时间我正在写一篇关于php.net的评论   Windows系统。后来,我不得不部分撤销我在那里写的内容   在另一条评论中对同一页面发表评论,其中也包含   一个可能解决问题的方法,这是我能想到的最容易的问题   (除了使用Composer)。

以下是原始答案的屏幕截图:

Original post

答案 3 :(得分:2)

请勿滚动自己的自动加载,而是使用composer

在项目的根目录中创建composer.json

{
    "autoload": {
        "psr-4": {
            "classes\\": "classes/"
        }
    }
}

安装composer,然后运行

 composer dump-autoload 

index.php中,需要自动加载器:

require __DIR__ . '/vendor/autoload.php';

供参考,见

答案 4 :(得分:0)

如果要加载的文件只有php扩展名,请不要使用spl_autoload_extensions()函数。 在我的例子中,我创建了一个名为autoload的类......类似于这个:

<?php

class Autoload
{
    private static $_extensions = array(
        0 => '.inc',
        1 => '.lib.php',
        2 => '.class.php',
    );

    public function __construct()
    {
        self::set_include_path();
        spl_autoload_extensions(implode(',', self::$_extensions));
        spl_autoload_register(__CLASS__, 'load_class');
    }

    public static function set_include_paths()
    {
        set_include_path(implode(PATH_SEPARATOR, array(
            realpath('classes');
            realpath('system');
            ...
            get_include_path();,
        )));
    }

    public function load_class($class)
    {
        if (!empty($class)) {
            spl_autoload($class);
        }

        return false;
    }
}

使用?>无需在文件末尾。