开发者

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

I am using Zend_Search_Lucene, to index my website. My site indexes are not entirely similar. Some have, few fields, and some have many fields. I am trying to create a similar index through different types of table, that's why i am encountering this kind of error.

Now, when I display the result. I call some fields, which are not present in all the result which generates the error. i tried to check it with isset but it seems it totally skips the row.

foreach ($hits as $hit开发者_StackOverflow) {
    $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>';
}

How to check if there is anything such as $hit -> name is present in $hit


The problem you are experiencing is very very specific and has to do with the Zend_Lucene_Search implementation, not the field/property exist check in general.

In your loop, $hit is an object of class Zend_Search_Lucene_Search_QueryHit. When you write the expression $hit->name, the object calls the magic __get function to give you a "virtual property" named name. It is this magic function that throws the exception if the value to be supplied does not exist.

Normally, when a class implements __get as a convenience it should also implement __isset as a convenience (otherwise you cannot really use isset on such virtual properties, as you have found out the hard way). Since this particular class does not implement __isset as IMHO it should, you will never be able to get the name "property" blindly without triggering an exception if the relevant data does not exist.

property_exists and all other forms of reflection will also not help since we are not talking about a real property here.

The proper way to solve this is a little roundabout:

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

All said, I 'd consider this a bug in ZF and probably file a report, asking for the __isset magic method to be implemented appropriately on the types it should be.


You can try 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>';
}


You can also use reflection to query what fields the object has and build your content in a more programmatic way. this is good if you have a ton of fields.

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

more info here : 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 will work if you simply convert your object to an array first.

<?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>';
?>
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜