检查字段/属性是否存在于object类型的变量中


Check if a field/propertry exists in a variable of type object

我使用Zend_Search_Lucene,索引我的网站。我的网站索引并不完全相似。有些人有很少的领域,有些人有很多领域。我试图通过不同类型的表创建一个类似的索引,这就是为什么我遇到这种错误。

现在,当我显示结果。我调用了一些字段,这些字段并不存在于生成错误的所有结果中。我试着用isset检查它,但它似乎完全跳过了这一行。

foreach ($hits as $hit) {
    $content .= '<div class="searchResult">';
      $content .= '<h2>';           
        $title = array();
        if(isset($hit -> name)) $title[] = $hit -> name;
        if(isset($hit -> title)) $title[] = $hit -> title;
            // This is the part where i get fatal error.
        $content .= implode(" &raquo; ",$title);
      $content .= '</h2>';
      $content .= '<p>'.$this->content.'</p>';
    $content .= '</div>';
}

如何检查$hit中是否存在$hit -> name等物质

您遇到的问题非常非常具体,与Zend_Lucene_Search实现有关,而不是一般的字段/属性存在检查。

在循环中,$hitZend_Search_Lucene_Search_QueryHit类的对象。当你写表达式$hit->name时,对象调用神奇的__get函数给你一个名为name的"虚拟属性"。如果要提供的值不存在,就是这个神奇的函数抛出异常。

通常,当一个类实现__get作为一个方便时,它也应该实现__isset作为一个方便(否则你不能真正在这样的虚拟属性上使用isset,因为你已经发现了困难的方式)。因为这个特定的类没有像我认为的那样实现__isset,如果相关数据不存在,你将永远无法盲目地获得name"属性"而不触发异常。

property_exists和所有其他形式的反射也没有帮助,因为我们在这里讨论的不是一个真实的属性。

解决这个问题的正确方法是:

$title = array();
$names = $hit->getDocument()->getFieldNames();
if(in_array('name', $names)) $title[] = $hit -> name;
if(in_array('title',$names)) $title[] = $hit -> title;

总而言之,我认为这是ZF的一个bug,可能会提交一份报告,要求__isset魔法方法在它应该的类型上适当地实现。

你可以试试property_exists

foreach ($hits as $hit) {
    $content .= '<div class="searchResult">';
      $content .= '<h2>';           
        $title = array();
        if(property_exists($hit, 'name')) $title[] = $hit -> name;
        if(property_exists($hit, 'title')) $title[] = $hit -> title;
            // This is the part where i get fatal error.
        $content .= implode(" &raquo; ",$title);
      $content .= '</h2>';
      $content .= '<p>'.$this->content.'</p>';
    $content .= '</div>';
}

您还可以使用反射来查询对象具有哪些字段,并以更程序化的方式构建内容。如果你有大量的字段,这是很好的。

$reflector = new ReflectionClass( get_class( $hit ) );
foreach( $reflector->getProperties() as $property  ) {
    if( in_array( $property->getName(), $SEARCH_FIELDS )
        $title[] = $property->getValue( $hit );
}

更多信息在这里:http://php.net/manual/en/book.reflection.php

# Verify if exists
$hits = $index->find('id_field:100');
if (isset($hits[0])) { echo 'true'; } else { echo 'false'; }
如果先将对象转换为数组,

isset就可以工作了。

<?php
class Obj {
    public function GetArr() {
        return (array)$this;
    }
    static public function GetObj() {
        $obj = new Obj();
        $obj->{'a'} = 1;
        return $obj;
    }
}
$o = 'Obj::GetObj();
$a = $o->GetArr();
echo 'is_array: ' . ('is_array($a) ? 1 : 0) . '<br />';
if ('is_array($a)) {
    echo '<pre>' . 'print_r($a, 'TRUE) . '</pre><br />';
}
echo '<pre>' . 'serialize($o) . '</pre>';
?>