【问题标题】:PHP - spl_autoload and namespaces - doesn't work with capital lettersPHP - spl_autoload 和命名空间 - 不适用于大写字母
【发布时间】:2020-04-19 22:11:24
【问题描述】:

我在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!';
    }
}

有效的代码

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


不起作用的东西

将我的核心文件夹重命名为“Core” - 请注意大写 C,以及 hello.php 中的命名空间@ 到 namespace Core;

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

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

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

【问题讨论】:

  • dirname(__FILE__) 是不必要的;你可以使用__DIR__
  • 谢谢!我会修改...

标签: php


【解决方案1】:

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

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

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

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

[编辑]

好的,所以我错过了您也更改了目录名。但是,我仍然认为这是文件名/目录名的问题。

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

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

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

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

我亲身经历了相反的情况,根据我的原始答案,我有一个完全小写的文件名,当我从 Windows 开发盒移动到 Linux 服务器时,我的混合大小写类名中断了。我的经验与您不同的原因是因为我使用的是自定义编写的自动加载函数,它不会进行自动小写转换,因此我的文件名的大小写必须与我的类名的大小写匹配。

【讨论】:

  • 不幸的是,这无济于事 - 正如已经说明的那样,肯定已经进行了,在对象声明、文件夹名称和命名空间中从 coreCorehello.php.
  • 嗯,好的,我也错过了关于您更改目录的内容。对不起。但请稍等——我想我已经发现了问题……我将编辑答案……
  • 啊,我明白了。我在那里的一个 cmets 中看到了以下内容:spl_autoload_register(function($class) { return spl_autoload(str_replace('\\', '/', $class)); }); - 任何进展,因为它似乎不起作用 - 允许大写?
  • @Jimbo - 不,如果你想让你的文件名大小写与类名相同,我认为你必须编写自己的 autload 函数而不是使用spl_autoload()。它不必很复杂;我的只有十几行左右。事实上,您可以从PSR-0 获取示例自动加载器代码。
  • 我想了很多 - 不过感谢您指出这一点,它有很大帮助,我相信它将来会对其他人有用:)
【解决方案2】:

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

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

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

【讨论】:

  • 其实,现在最适合这项工作的最佳工具是 Composer。如果您开始使用它,它会为您整理出所有的命名空间,您只需在文件顶部包含 vendor/autoload.php 即可自动解析所有命名空间。
  • 我在安装 Zend2 框架时被介绍给 composer。它确实是一个很好的工具,而且我也想深入了解一下。
【解决方案3】:

对于其他对此有疑问的人,为什么不使用 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');
    }
});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-05
    相关资源
    最近更新 更多