PHP - spl_autoload和名称空间 - 不适用于大写字母

时间:2013-02-22 15:26:17

标签: php

我在index.php中设置了一个非常基本的自动加载器,以便在hello.php内获取命名空间类。我的开发环境是 Ubuntu 12.04

为什么我要这样做?我正在努力坚持PSR-1PSR-2 coding standard,其中包括:

  

类名必须在StudlyCaps中声明

     

命名空间为/ Vendor / Class(注意:大写)

以下是我的结构和代码 之前 进行更改。

文件夹结构

- web
  -- index.php
  -- core
    --- hello.php

自动装

在index.php中,我有自动加载器:

set_include_path(__DIR__);
spl_autoload_extensions('.php,.class.php');
spl_autoload_register();

类文件

在核心文件夹中,我有hello.php

namespace core;

class hello {
    public function __construct() {
        echo 'Constructed!';
    }
}

有效的代码

如果我在$obj = new \core\hello();中运行index.php,我会回复“构建!”。太好了!


不起作用的

将我的核心文件夹重命名为'Core' - 请注意大写C,以及hello.phpnamespace Core;中的命名空间。

现在让我们再试一次$obj = new \Core\hello();

Fatal error: Class 'Core\hello' not found in ...

所以请告诉我,为什么我不能用大写字母来保持符合PSR标准?我做错了什么?

3 个答案:

答案 0 :(得分:8)

当您在Linux平台上运行PHP代码时,请务必记住Linux对文件名区分大小写。

这会影响自动加载器,因为它们通常在构建要加载的文件名时使用命名空间和类名。

如果文件夹名为core,则名称空间必须为core,且大小写相同。如果在命名空间中将其更改为Core,则必须对文件夹名称执行相同操作。 (因此,所有其他core类必须同时更改为Core

在Windows上,这不会发生,因为Windows文件系统不区分大小写。这可能会在代码经过测试并在基于Windows的本地开发系统上运行时造成混淆,然后在复制到基于Linux的服务器时中断。

[编辑]

好的,所以我错过了你也改变了dirname。但是,我仍然认为这是filename / dirname案例的问题。

我注意到你在没有任何参数的情况下呼叫spl_autoload_register()。这意味着默认的spl_autoload()函数将用作自动加载器。

如果您阅读the documentation for spl_autoload(),则会注意到它使用了类和命名空间的 lowercased 版本。

换句话说,使用默认的自动加载器,您的类可以是大小写混合,但文件夹结构和文件名必须全部小写。

事实上,对你来说,你需要保持文件名小写。

我个人经历了反过来,根据我的原始答案,我有一个完全小写的文件名,当我从Windows开发盒移动到Linux服务器时,我的混合案例类名称破了。究其原因我的经验和你不一样,因为我使用的是自定义编写的自动加载功能,它没有做自动转换小写,所以我的文件名的情况下,必须匹配,我的类名的。

答案 1 :(得分:2)

我认为你向我们展示了一些不好的歧义。如果我错了,请更正我。

根据规范,您必须使用正在实例化的类(和名称空间)的小写名称。(http://www.php.net/manual/en/function.spl-autoload.php

但PSR告诉我们使用大写字母。如果你想坚持使用PSR,那么我们必须将默认的spl_autoload覆盖为我们自己的。

答案 2 :(得分:1)

对于其他任何有此问题的人,为什么不使用ucfirst()或strtolower()?

因此,下面的代码将尝试全部小写,并尝试首字母大写文件

例如:somename.class.php或Somename.class.php

is_readable()首先检查是否显示未找到文件的php错误。

spl_autoload_register(function($name) {

    if (is_readable(strtolower($name).'.class.php')) {
        require_once(strtolower($name).'.class.php');
    } 
    elseif (is_readable(ucfirst($name).'.class.php')) {
        require_once(ucfirst($name).'.class.php');
    }
});