如何通过自动加载使用 PHP 命名空间?
当我尝试使用自动加载和命名空间时出现此错误:
致命错误:在 /usr/local/www/apache22/data/public/php5.3/test.php 上找不到类“Class1” >第 10 行
谁能告诉我我做错了什么?
这是我的代码:
Class1.php:
<?php
namespace Person\Barnes\David
{
class Class1
{
public function __construct()
{
echo __CLASS__;
}
}
}
?>
test.php:
<?php
function __autoload($class)
{
require $class . '.php';
}
use Person\Barnes\David;
$class = new Class1();
?>
I get this error when I try to use autoload and namespaces:
Fatal error: Class 'Class1' not found in /usr/local/www/apache22/data/public/php5.3/test.php on line 10
Can anyone tell me what I am doing wrong?
Here is my code:
Class1.php:
<?php
namespace Person\Barnes\David
{
class Class1
{
public function __construct()
{
echo __CLASS__;
}
}
}
?>
test.php:
<?php
function __autoload($class)
{
require $class . '.php';
}
use Person\Barnes\David;
$class = new Class1();
?>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(13)
Class1
不在全局范围内。请注意,这是一个旧的答案,自从您无法假设对 PHP 5.1 中引入的
spl_autoload_register()
支持以来,事情已经发生了变化(现在很多年前了!)。如今,您可能会使用 Composer。在幕后,这将是沿着此代码段的内容,以启用 class自动加载。
为了完整起见,这里是旧的答案:
要加载未在全局范围内定义的类,您需要使用自动加载器。
或没有别名:
Class1
is not in the global scope.Note that this is an old answer and things have changed since the days where you couldn't assume the support for
spl_autoload_register()
which was introduced in PHP 5.1 (now many years ago!).These days, you would likely be using Composer. Under the hood, this would be something along the lines of this snippet to enable class autoloading.
For completeness, here is the old answer:
To load a class that is not defined in the global scope, you need to use an autoloader.
or without aliases:
正如 Pascal MARTIN 提到的,您应该将 '\' 替换为 DIRECTORY_SEPARATOR 例如:
另外,我建议您重新组织目录结构,以使代码更具可读性。这可能是一种替代方案:
目录结构:
文件:
/ProjectRoot/lib/Person/Barnes/David/Class1.php
文件:
/ProjectRoot/test.php
As mentioned Pascal MARTIN, you should replace the '\' with DIRECTORY_SEPARATOR for example:
Also I would suggest you to reorganize the dirrectory structure, to make the code more readable. This could be an alternative:
Directory structure:
File:
/ProjectRoot/lib/Person/Barnes/David/Class1.php
File:
/ProjectRoot/test.php
您的 __autoload 函数将接收完整的类名,包括命名空间名称。
这意味着,在您的情况下,
__autoload
函数将接收“Person\Barnes\David\Class1
”,而不仅仅是“Class1
”。所以,你必须修改你的自动加载代码,来处理那种“更复杂”的名字;经常使用的解决方案是使用命名空间的每个“级别”使用一级目录来组织文件,并且在自动加载时,将命名空间名称中的“
\
”替换为DIRECTORY_SEPARATOR
。Your
__autoload
function will receive the full class-name, including the namespace name.This means, in your case, the
__autoload
function will receive 'Person\Barnes\David\Class1
', and not only 'Class1
'.So, you have to modify your autoloading code, to deal with that kind of "more-complicated" name ; a solution often used is to organize your files using one level of directory per "level" of namespaces, and, when autoloading, replace '
\
' in the namespace name byDIRECTORY_SEPARATOR
.我做了这样的事情: 查看此 GitHub 示例
I do something like this: See this GitHub Example
我看到自动加载函数仅在以下两种情况下接收“完整”类名 - 及其前面的所有命名空间:
我看到自动加载函数在以下情况下不接收完整类名:
更新:[c] 是这是一个错误,而且这并不是命名空间的工作方式。我可以报告说,除了 [c],以下两种情况也能很好地工作:
希望这会有所帮助。
I see that the autoload functions only receive the "full" classname - with all the namespaces preceeding it - in the following two cases:
I see that the autoload functions DO NOT receive the full classname in the following case:
UPDATE: [c] is a mistake and isn't how namespaces work anyway. I can report that, instead of [c], the following two cases also work well:
Hope this helps.
我从 Flysystem 找到了这个宝石
I found this gem from Flysystem
我在一行中使用了这个简单的技巧:
I use this simple hack in one line:
https://thomashunter.name/blog/simple-php-namespace -Friendly-autoloader-class/
您需要将类文件放入名为
Classes
的文件夹中,该文件夹与 PHP 应用程序的入口点位于同一目录中。如果类使用命名空间,则命名空间将转换为目录结构。与许多其他自动加载器不同,下划线不会转换为目录结构(将 PHP < 5.3 伪命名空间与 PHP >= 5.3 真实命名空间一起处理是很棘手的)。
您需要将以下代码放入主 PHP 脚本(入口点)中:
这是一个示例目录布局:
https://thomashunter.name/blog/simple-php-namespace-friendly-autoloader-class/
You’ll want to put your class files into a folder named
Classes
, which is in the same directory as the entry point into your PHP application. If classes use namespaces, the namespaces will be converted into the directory structure.Unlike a lot of other auto-loaders, underscores will not be converted into directory structures (it’s tricky to do PHP < 5.3 pseudo namespaces along with PHP >= 5.3 real namespaces).
You’ll want to place the following code into your main PHP script (entry point):
Here’s an example directory layout:
遇到了同样的问题,刚刚发现了这个:
当您创建与包含类的名称空间匹配的子文件夹结构时,您甚至不必定义自动加载器。
它的工作就像一个魅力
更多信息在这里:http:// /www.php.net/manual/en/function.spl-autoload-register.php#92514
编辑:由于反斜杠,这会在 Linux 上导致问题...请参阅此处,了解 immeëmosol 的工作解决方案
命名空间自动加载在 Windows 下有效,但在 Linux 上无效
had the same issue and just found this :
When you create a subfolder structure matching the namespaces of the containing classes, you will never even have to define an autoloader.
It worked like a charm
More info here : http://www.php.net/manual/en/function.spl-autoload-register.php#92514
EDIT: this causes problem on Linux because of backslash... See here for working solution by immeëmosol
Namespace Autoload works under windows, but not on Linux
使用有一个陷阱,虽然它是迄今为止最快的方法,但它也要求所有文件名都是小写的。
例如:
包含类 SomeSuperClass 的文件需要命名为 somesuperclass.php,如果您的文件名为 SomeSuperClass.php 但在 Windows 下不是问题,那么在使用 Linux 等区分大小写的文件系统时,这是一个问题。
在代码中使用 __autoload 可能仍然适用于当前版本的 PHP,但预计此功能将被弃用并最终在将来被删除。
那么还剩下什么选项:
这个版本将与 PHP 5.3 及更高版本一起使用,并允许文件名 SomeSuperClass.php 和 somesuperclass.php。如果您使用 5.3.2 及更高版本,此自动加载器的运行速度会更快。
Using has a gotcha, while it is by far the fastest method, it also expects all of your filenames to be lowercase.
For example:
A file containing the class SomeSuperClass would need to be named somesuperclass.php, this is a gotcha when using a case sensitive filesystem like Linux, if your file is named SomeSuperClass.php but not a problem under Windows.
Using __autoload in your code may still work with current versions of PHP but expect this feature to become deprecated and finally removed in the future.
So what options are left:
This version will work with PHP 5.3 and above and allows for filenames SomeSuperClass.php and somesuperclass.php. If your using 5.3.2 and above, this autoloader will work even faster.
对于相对初学者或者想要一个简单的 spl_autoload_register() 设置而不需要所有理论的人,我将投入两分钱:
只需为每个类创建一个 php 文件,将该 php 文件命名为与类名相同的名称,并将类文件与相关 php 文件放在同一目录中,然后这将起作用:
谷歌搜索此函数内的各个部分应该回答如何有用。
PS:我使用Linux,这可以在Linux上运行。 Windows 用户应该首先测试一下。
I'll throw in my two cents for relative beginners or whatnot wanting a simple spl_autoload_register() setup without all the theory:
Just create one php file for each class, name that php file the same as your class name, and keep your class files in the same directory as your php file in question, then this will work:
Googling the pieces inside this function should answer how it works.
PS: I use Linux, and this works on Linux. Windows folks should test it out first.
我最近发现 tanerkay 的回答非常有帮助!只是想补充一点,使用
strrpos()
+substr()
比explode()
+end()
稍快一些代码>:I recently found tanerkay's answer very helpful! Just wanted to add that using
strrpos()
+substr()
is slightly faster thanexplode()
+end()
: