如何在 PHP 中检查特定类型的对象

How to Check for a Specific Type of Object in PHP

提问人:Madara's Ghost 提问时间:11/11/2011 最后编辑:BenMadara's Ghost 更新时间:3/4/2015 访问量:53176

问:

我有一个接受PDO对象作为参数的方法,允许用户使用现有连接而不是打开新连接的方法,并节省资源:

public static function databaseConnect($pdo = null) {

我知道要检查参数是否是对象,但我想检查是否是 PDO 对象,而不仅仅是一个对象。is_object()$pdo

因为用户可以很容易地输入(错误地?)不同类型的对象,mysqli之类的,整个脚本就会分解。

简而言之:如何检查特定类型对象的变量?

php oop 对象类型

评论


答:

98赞 Dan Lugg 11/11/2011 #1

您可以使用 instanceof

if ($pdo instanceof PDO) {
    // it's PDO
}

但要注意,你不能像 否定,所以你应该这样做:!instanceof

if (!($pdo instanceof PDO)) {
    // it's not PDO
}

此外,在查看您的问题时,您可以使用对象类型提示,这有助于强制执行要求,并简化检查逻辑:

function connect(PDO $pdo = null)
{
    if (null !== $pdo) {
        // it's PDO since it can only be
        // NULL or a PDO object (or a sub-type of PDO)
    }
}

connect(new SomeClass()); // fatal error, if SomeClass doesn't extend PDO

类型化参数可以是必需的,也可以是可选的:

// required, only PDO (and sub-types) are valid
function connect(PDO $pdo) { }

// optional, only PDO (and sub-types) and 
// NULL (can be omitted) are valid
function connect(PDO $pdo = null) { }

非类型化参数允许通过显式条件实现灵活性:

// accepts any argument, checks for PDO in body
function connect($pdo)
{
    if ($pdo instanceof PDO) {
        // ...
    }
}

// accepts any argument, checks for non-PDO in body
function connect($pdo)
{
    if (!($pdo instanceof PDO)) {
        // ...
    }
}

// accepts any argument, checks for method existance
function connect($pdo)
{
    if (method_exists($pdo, 'query')) {
        // ...
    }
}

至于后者(使用method_exists),我的观点有点复杂。来自 Ruby 的人会发现它对respond_to很熟悉,不管是好是坏。我个人会编写一个接口并对此执行正常的类型提示:

interface QueryableInterface
{ 
    function query();
}

class MyPDO extends PDO implements QueryableInterface { }

function connect(QueryableInterface $queryable) { }

然而,这并不总是可行的。在此示例中,对象不是有效的参数,因为基类型未实现。PDOQueryableInterface

还值得一提的是,值在 PHP 中具有类型,而不是变量。这很重要,因为检查将失败。nullinstanceof

$object = new Object();
$object = null;
if ($object instanceof Object) {
    // never run because $object is simply null
}

当值变成 时,该值将失去它的类型,即缺少类型。null

评论

1赞 Madara's Ghost 11/11/2011
我认为PHP中不允许类型提示
0赞 Dan Lugg 11/11/2011
当然是,但仅适用于 和 对象类类型。因此,任何用户空间类都很好,就像我的例子一样。但是,您不能暗示标量,例如 .ArrayPDOstring
0赞 Madara's Ghost 11/11/2011
我明白了,虽然我不想要致命错误,但我想要抛出异常。很高兴知道:)
0赞 Dan Lugg 11/11/2011
@Truth - 我认为这是一个可捕获的致命错误,你必须检查。如果你错误地处理成,我认为它会被转换。ErrorException
2赞 Dan Lugg 8/12/2017
@davidkonrad 自本文(PHP 5.3)以来,PHP 的词法分析器/解析器有了显着改进,因此也许它增加了对直接否定运算符的支持。
2赞 Sarfraz 11/11/2011 #2

我认为您可以使用 instanceof 这样的东西:

if ($pdo instanceof YOUR_PDO_OBJECT_INSTANCE) {
   // it is...
}
11赞 Oliver A. 11/11/2011 #3

 bool is_a ( object $object , string $class_name )

这也适用于子类。

查看 http://php.net/is-a

编辑: 或者您可以使用类型提示:

public static function databaseConnect(PDO $pdo = null) {...

评论

1赞 Madara's Ghost 11/11/2011
这和有什么区别(请注意,我可能会在几秒钟内在谷歌中找到它,我是故意问的,以便未来的用户看到它)instanceof
0赞 Oliver A. 11/11/2011
is_a将字符串作为第二个参数,因此现在不能在设计时检查类。我用它来从xml创建ojects。我的反序列化程序解析 xml 查找类似 <class>my\ns\user</class>然后创建 my\ns\user 的新实例并注入所有属性和依赖项。如果希望对象加载器返回某种类型的对象,可以设置属性$desiredClass,然后使用 is_a($createdObject, $this->desiredClass)
1赞 coatesap 11/27/2013
@MadaraUchiha - stackoverflow.com/questions/3017684/... 可能有用
3赞 Weston C 11/11/2011 #4

正如其他答案中指出的,、、和可能是你要找的。instanceofget_classis_a

然而,一些开发人员发现,与其编写大量测试类型的保护程序,不如让运行时处理强制执行更有效率(也更易于阅读),尤其是当你谈论其他程序员将要进行的调用时(当程序员犯错误时,破坏应用程序的大声抱怨可以说是一件好事)。

如果你真的不需要在程序员错误地使用你的方法时让脚本分崩离析,那么将代码的相关部分(在本例中,可能是 databaseConnect 的内部)包装在一个 try 块中,也许使用 set_error_handler 在脚本错误时抛出异常,然后设置一个或多个 catch ,指示在发生异常情况时该怎么做。