令人惊讶的是,没有人提到这样做的明显原因:use
关键字只能在最外层范围内使用,并且在编译时处理,因此您不能use Some\Class
基于某些条件,也不能是块范围:
namespace Foo;
if (!extension_loaded('gd'))
{
use Images\MagicImage as Image;
}
else
{
use Images\GdImage as Image;
}
class ImageRenderer
{
public function __construct(Image $img)
{}
}
这是行不通的:尽管use
语句在最外层范围内,但正如我之前所说,这些导入是在编译时执行的,而不是在运行时执行的。结果,这段代码的行为就好像它是这样编写的:
namespace Foo;
use Images\GdImage as Image;
use Images\MagicImage as Image;
这将产生一个错误(具有相同别名的 2 个类......)
class_alias
但是,它是一个在运行时调用的函数,因此它可以是块范围的,并且可以用于条件导入:
namespace Foo;
if (!extension_loaded('gd'))
{
class_alias('Images\\MagicImage', 'Image');
}
else
{
class_alias('Images\\GdImage','Image');
}
class ImageRenderer
{
public function __construct(Image $img)
{}
}
除此之外,我怀疑它的主要好处class_alias
是在 PHP 5.3(引入了命名空间)之前编写的所有代码都允许您避免编写如下内容:
$foo = new My_Lib_With_Pseudo_Name_Spaces_Class();
不必重构整个代码库并创建命名空间,添加几个更容易:
class_alias('My_Lib_With_Pseudo_Name_Spaces_Class', 'MyClass');
到脚本的顶部,以及一些//TODO: switch to Namespaces
评论。
另一个用例可能是在将这些类实际转移到它们的命名空间对应物时:只需在class_alias
一个类被重构后更改调用,其他类就可以保持不变。
在重构代码时,您可能会想要重新考虑一些事情,因此像 aichingm 这样的用例建议可能不会太牵强。
我能想到的最后一件事,但我还没有看到,当你想用一个模拟对象测试一些代码时,你可能会使用它class_alias
来使一切顺利运行。但是,如果你必须这样做,你也可以认为测试失败,因为这表明代码写得不好,IMO。
顺便说一句,就在今天,我遇到了class_alias
. 我正在研究一种实现库的方法,该库从 CLI 工具中提炼出来,用于基于 MVC 的 Web 应用程序。一些类依赖于要传递的调用命令的实例,它们从中获得了一些其他的细节。
我没有经历重构的麻烦,而是决定替换:
use Application\Commands\SomeCommand as Invoker;
声明:
if (\PHP_SAPI === 'cli')
{
class_alias('\\Application\\Commands\\SomeCommand', 'Invoker');
}
else
{
class_alias('\\Web\\Models\\Services\\SomeService', 'Invoker');
}
而且,在快速:%s/SomeCommand/Invoker/g
使用vim之后,我很高兴(或多或少)