PHP 自动加载 类 不使用命名空间
PHP Autoload Classes Is Not Working With Namespaces
我曾尝试编写以下代码,但无法弄清楚为什么它在 spl_autoload_register() 中找不到带有命名空间的 class?
我得到的错误是:
Warning: require_once(src/test\StringHelper.php): failed to open
stream: No such file or directory
Autoloader.php 文件:
<?php
spl_autoload_register(function($classname){
require_once "src/$classname.php"; // NOT WORKING DYNAMICALLY
// require_once "src/StringHelper.php"; // WORKING WHEN HARD CODED
});
$stringHelper1 = new test\StringHelper(); // Class with namespace defined
echo $stringHelper1->hello() . PHP_EOL; // returns text
StringHelper.php 在 src 文件夹内:
<?php namespace test;
class StringHelper{
function hello(){
echo "hello from string helper";
}
}
我也在使用 XAMPP 如果这有什么不同的话。
正如评论中已经指出的那样,您需要删除 class 名称以外的所有内容,如下所示:
$classname = substr($classname, strrpos($classname, "\") + 1);
在您的自动加载功能的上下文中:
spl_autoload_register(function($classname){
$classname = substr($classname, strrpos($classname, "\") + 1);
require_once "src/{$classname}.php";
});
让我们更进一步,利用自动加载函数总是接收 合格命名空间 而不是 相对的这一事实命名空间:
<?php
namespace Acme;
$foo = new \Acme\Foo(); // Fully qualified namespace
$foo = new Acme\Foo(); // Qualified namespace
$foo = new Foo(); // Relative namespace
在所有三个实例中,我们的自动加载函数总是以 Acme\Foo
作为参数。考虑到这一点,实现将命名空间和任何子命名空间映射到文件系统路径的自动加载器策略相当容易 - 特别是如果我们在文件系统层次结构。
例如,在我们的某个项目中给出这两个 classes...
<?php
namespace Acme;
class Foo {}
Foo.php
<?php
namespace Acme\Bar;
class Bar {}
Bar.php
...在此文件系统布局中...
my-project
`-- library
`-- Acme
|-- Bar
| `-- Bar.php
`-- Foo.php
...我们可以在命名空间 class 和它的物理位置之间实现一个简单的映射,如下所示:
<?php
namespace Acme;
const LIBRARY_DIR = __DIR__.'/lib'; // Where our classes reside
/**
* Autoload classes within the current namespace
*/
spl_autoload_register(function($qualified_class_name) {
$filepath = str_replace(
'\', // Replace all namespace separators...
'/', // ...with their file system equivalents
LIBRARY_DIR."/{$qualified_class_name}.php"
);
if (is_file($filepath)) {
require_once $filepath;
}
});
new Foo();
new Bar\Bar();
另请注意,您可以注册多个自动加载函数,例如,以处理不同物理位置的不同顶级命名空间。不过,在实际项目中,您可能希望熟悉 Composer 的自动加载机制:
- https://getcomposer.org/doc/01-basic-usage.md#autoloading
- https://getcomposer.org/doc/04-schema.md#autoload
- https://getcomposer.org/doc/articles/autoloader-optimization.md
有时,您可能还想查看 PHP 的自动加载规范:
我曾尝试编写以下代码,但无法弄清楚为什么它在 spl_autoload_register() 中找不到带有命名空间的 class?
我得到的错误是:
Warning: require_once(src/test\StringHelper.php): failed to open stream: No such file or directory
Autoloader.php 文件:
<?php
spl_autoload_register(function($classname){
require_once "src/$classname.php"; // NOT WORKING DYNAMICALLY
// require_once "src/StringHelper.php"; // WORKING WHEN HARD CODED
});
$stringHelper1 = new test\StringHelper(); // Class with namespace defined
echo $stringHelper1->hello() . PHP_EOL; // returns text
StringHelper.php 在 src 文件夹内:
<?php namespace test;
class StringHelper{
function hello(){
echo "hello from string helper";
}
}
我也在使用 XAMPP 如果这有什么不同的话。
正如评论中已经指出的那样,您需要删除 class 名称以外的所有内容,如下所示:
$classname = substr($classname, strrpos($classname, "\") + 1);
在您的自动加载功能的上下文中:
spl_autoload_register(function($classname){
$classname = substr($classname, strrpos($classname, "\") + 1);
require_once "src/{$classname}.php";
});
让我们更进一步,利用自动加载函数总是接收 合格命名空间 而不是 相对的这一事实命名空间:
<?php
namespace Acme;
$foo = new \Acme\Foo(); // Fully qualified namespace
$foo = new Acme\Foo(); // Qualified namespace
$foo = new Foo(); // Relative namespace
在所有三个实例中,我们的自动加载函数总是以 Acme\Foo
作为参数。考虑到这一点,实现将命名空间和任何子命名空间映射到文件系统路径的自动加载器策略相当容易 - 特别是如果我们在文件系统层次结构。
例如,在我们的某个项目中给出这两个 classes...
<?php
namespace Acme;
class Foo {}
Foo.php
<?php
namespace Acme\Bar;
class Bar {}
Bar.php
...在此文件系统布局中...
my-project
`-- library
`-- Acme
|-- Bar
| `-- Bar.php
`-- Foo.php
...我们可以在命名空间 class 和它的物理位置之间实现一个简单的映射,如下所示:
<?php
namespace Acme;
const LIBRARY_DIR = __DIR__.'/lib'; // Where our classes reside
/**
* Autoload classes within the current namespace
*/
spl_autoload_register(function($qualified_class_name) {
$filepath = str_replace(
'\', // Replace all namespace separators...
'/', // ...with their file system equivalents
LIBRARY_DIR."/{$qualified_class_name}.php"
);
if (is_file($filepath)) {
require_once $filepath;
}
});
new Foo();
new Bar\Bar();
另请注意,您可以注册多个自动加载函数,例如,以处理不同物理位置的不同顶级命名空间。不过,在实际项目中,您可能希望熟悉 Composer 的自动加载机制:
- https://getcomposer.org/doc/01-basic-usage.md#autoloading
- https://getcomposer.org/doc/04-schema.md#autoload
- https://getcomposer.org/doc/articles/autoloader-optimization.md
有时,您可能还想查看 PHP 的自动加载规范: