28

我们为什么要使用这个class_alias功能?例如:

Class Test {
 public function __construct(){
   echo "Class initialized"; 
 }
}

class_alias("Test", "AnotherName"); 

$instance = new AnotherName();   # equivalent to $instance = new Test();

根据手册,“别名类与原始类完全相同。”

这有什么用?

4

3 回答 3

47

令人惊讶的是,没有人提到这样做的明显原因: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之后,我很高兴(或多或少)

于 2013-07-30T08:46:52.400 回答
9

换个方式想想这个。有一个库,它包含一个名为 MySq 的类,随着库的发展,他们认为“哦,也许我们应该只创建一个数据库类”,因此重写该类并将其称为“DatabaseConnection”,它具有与MySql 类,但它也可以处理 Sql 和 MsSql。随着时间的推移,他们发布了新版本“PHPLib2”。开发人员现在有两个选择:1,告诉用户从 MySql 更改为 DatabaseConnection 或 2,开发人员使用

class_alias("DatabaseConnection","MySql"); 

并将类 MySql 标记为已弃用。

tltr;

保持版本兼容性!

于 2013-07-20T17:58:00.947 回答
2

它可用于:

  1. 更改 ext 的奇怪类名。脚本/来源(无需重写代码)
  2. 使类名更短(类别名可以在应用程序范围内使用)
  3. 将类移动到另一个命名空间 (@tlenss)
于 2013-07-20T17:45:28.060 回答