令人惊讶的是,没有人提到为什么要这样做的明显原因:关键字只能在最外围的范围内使用,并且在编译时处理,因此您不能基于某些条件,也不能将其设置为块范围: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)
{}
}
除此之外,我怀疑它的主要好处是,在PHP 5.3(引入了命名空间)之前编写的所有代码都允许您避免编写如下内容:class_alias
$foo = new My_Lib_With_Pseudo_Name_Spaces_Class();
不必重构整个代码库并创建命名空间,添加几个代码就容易得多:
class_alias('My_Lib_With_Pseudo_Name_Spaces_Class', 'MyClass');
到脚本的顶部,以及一些注释。//TODO: switch to Namespaces
另一个用例可能是在实际将这些类转移到它们的命名空间对应项时:只需在重构一个类后更改调用,其他类就可以保持不变。
在重构代码时,您很可能会想要重新考虑一些事情,因此像aichinm建议的用例可能不会太牵强。class_alias
我能想到的最后一件事,但我还没有看到这一点,当你想用一个模拟对象测试一些代码时,你可以用它来使一切顺利运行。但是,如果您必须这样做,则可能会将测试视为失败,因为这表明代码编写得很糟糕,IMO。class_alias
顺便说一句,就在今天,我遇到了另一个用例。我正在研究一种实现lib的方法,该库是从CLI工具中提取的,用于基于MVC的Web应用程序。一些类依赖于要传递的被调用命令的实例,它们从中获取了一些其他位和螺栓。
我没有经历重构的麻烦,而是决定替换:class_alias
use Application\Commands\SomeCommand as Invoker;
语句包含:
if (\PHP_SAPI === 'cli')
{
class_alias('\\Application\\Commands\\SomeCommand', 'Invoker');
}
else
{
class_alias('\\Web\\Models\\Services\\SomeService', 'Invoker');
}
而且,在快速的vim之后,我很高兴(或多或少):%s/SomeCommand/Invoker/g