PHP 7 在使用 'MyClass::class' 表示法时,是否有办法在不存在的类上崩溃?



一个基本的用例是在没有导入use MyNamespaceMyEventListener的情况下调用MyEventListener::class。结果将是一段相对难以调试的损坏代码。

如果不存在类,PHP 7 是否提供崩溃指令而不是返回类名?例如:

打电话给use FooBar;后,Bar::class会返回'FooBar'

但是如果没有导入语句,PHP 会返回'Bar',即使该类不存在,甚至在全局命名空间中也不存在。

我可以以某种方式让它崩溃吗?

您需要记住的是,use FooBar;并没有"导入"任何东西。它告诉编译器:当我说"Bar"时,我的意思是Bar来自命名空间Foo

Bar::class被盲目地替换为字符串"Foo\Bar"。它没有检查任何东西。

在您尝试实例化类或与类交互之前,它不会检查它是否存在。也就是说,它不会抛出Exception,而是抛出Error

// this doesn't exist!
use Foo/Bar;
try {
$instanceOfBar = new Bar();
}
catch (Error $e) {
// catching an Exception will not work
// Throwable or Error will work
}

您可以在运行时捕获和检查不存在的类,但在您这样做之前,它会很乐意折腾引用不存在的类的字符串。

对于 Laravel 的 IoC 容器和自动加载器来说,这是一种祝福,它滥用它来将类别名为方便的顶级对象。一个诅咒,如果你期望PHP对不存在::class大惊小怪。


更新:对于担心此问题的人,我的建议是在测试管道中使用PHPStan。它可以防止很多错误,并且与php -l不同的是,如果您要尝试与不存在的类进行交互,它将捕获。

据我所知,当您尝试实例化无法通过自动加载或显式添加找到的类时,您将收到一条很好的错误消息。

如果要检查该类是否存在,首先,请尝试以下操作:

$classOutsideNamespaceExists = class_exists('Bar');
$classInsideNameSpaceExists = class_exists('\Foo\Bar'));

或者你可以试试这个从 PHP 5.5 开始可用的语法:

class_exists(MyClass::class)

最后,您始终可以使用 try-catch 块的 try 和 true 方法。

try {
$instanceOfMyClass = new MyClass();
}
catch (Exception $e) {
// conclude the class does not exist and handle accordingly
}

PhpStorm 提出并生成提示,如ArrayShapePure等。

但它会自动添加

php use JetBrainsPhpStormArrayShape;

或其他。

在某些生产服务器上我会出错并不是那么危险 "Class JetBrains\PhpStorm\ArrayShape not found"?

(c)懒人:

  1. 好吧,只需使用作曲家要求--dev jetbrains/phpstorm-attributes将此类类添加到您的项目中。请参阅 github.com/JetBrains/phpstorm-attributes

  2. 只要此类的实例实际上没有被实例化(创建),就应该没有错误,因为 use 语句只是一个声明。

相关内容

最新更新