我在index.php
中设置了一个非常基本的自动加载器,以便在hello.php
内获取命名空间类。我的开发环境是 Ubuntu 12.04 。
为什么我要这样做?我正在努力坚持PSR-1和PSR-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.php
到namespace Core;
中的命名空间。
现在让我们再试一次$obj = new \Core\hello();
Fatal error: Class 'Core\hello' not found in ...
所以请告诉我,为什么我不能用大写字母来保持符合PSR标准?我做错了什么?
答案 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');
}
});