【问题标题】:How to Check for a Specific Type of Object in PHP如何在 PHP 中检查特定类型的对象
【发布时间】:2011-12-26 19:53:57
【问题描述】:

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

public static function databaseConnect($pdo = null) {

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

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

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

【问题讨论】:

    标签: php oop object-type


    【解决方案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) { }
    

    但是,这并不总是可行;在此示例中,PDO 对象不是有效参数,因为基类型未实现 QueryableInterface

    还值得一提的是,值在 PHP 中具有类型,而不是变量。这很重要,因为null 将无法通过instanceof 检查。

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

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

    【讨论】:

    • 我认为 PHP 中不允许使用类型提示
    • 确实如此,但仅适用于Array 和对象类类型。所以PDO 和任何用户级类都很好,就像我的例子一样。但是,您不能提示标量,例如 string
    • 我明白了,虽然我不想要致命错误,但我想要抛出异常。不过很高兴知道:)
    • @Truth - 我认为这是一个可捕获的致命错误,您必须检查一下。如果您将错误句柄转换为ErrorException,我认为它会被转换。
    • @davidkonrad 自从这篇文章(PHP 5.3)以来,PHP 的词法分析器/解析器有了显着的改进,所以它可能增加了对直接否定运算符的支持。
    【解决方案2】:

    使用

     bool is_a ( object $object , string $class_name )
    

    这也适用于子类。

    http://php.net/is-a

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

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

    【讨论】:

    • 这和instanceof有什么区别(注意我在google里大概几秒就可以找到,我特意问一下,让以后的用户看到)
    • is_a 将字符串作为第二个参数,因此您现在不能在设计时检查您的类。我用它从 xml 创建对象。我的 Unserializer 解析 xml 查找类似 my\ns\user 的 ndoe,然后创建 my\ns\user 的新实例并注入所有属性和依赖项。如果您希望对象加载器返回某种类型的对象,您可以设置属性 $desiredClass 然后使用 is_a($createdObject, $this->desiredClass)
    • @MadaraUchiha - stackoverflow.com/questions/3017684/… 可能有用
    【解决方案3】:

    正如其他答案中指出的那样,instanceofget_classis_a 可能是您正在寻找的。​​p>

    然而,一些开发人员发现,让运行时处理强制执行,而不是在许多测试类型的守卫中进行编码,效率更高(并且更易于阅读),尤其是当您谈论其他程序员会调用的调用时正在做(当程序员犯错时,应用程序崩溃的大声抱怨可以说是一件好事)。

    如果您确实需要在程序员错误地使用您的方法时不让脚本崩溃,请将相关的代码部分(在这种情况下,可能是 databaseConnect 的内部)包装在 try block 中,也许使用 set_error_handler在脚本错误时抛出异常,然后设置一个或多个 catch 块,指示发生异常情况时要做什么。

    【讨论】:

      【解决方案4】:

      我认为你可以使用 instanceof 类似的东西:

      if ($pdo instanceof YOUR_PDO_OBJECT_INSTANCE) {
         // it is...
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-09-23
        • 2011-10-16
        • 1970-01-01
        • 1970-01-01
        • 2013-09-12
        • 2012-10-09
        • 2011-01-27
        • 2011-01-25
        相关资源
        最近更新 更多