1

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) {
    $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

mrN
  • 3,734
  • 15
  • 58
  • 82
  • Does it skip the row or do you get a PHP error? You seem indecisive. – Jon Apr 11 '11 at 14:20
  • Of course error `Fatal error: Uncaught exception 'Zend_Search_Lucene_Exception' with message 'Field name "name" not found in document` – mrN Apr 11 '11 at 14:24
  • I just solved the problem, but keep in mind that if you had not given the exact error message I would never have been able to. In the future, please post *all relevant messages* when asking the question. Don't leave people guessing, it makes it harder for *you* to get help. – Jon Apr 11 '11 at 14:54

5 Answers5

5

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.

Jon
  • 428,835
  • 81
  • 738
  • 806
0

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>';
}
Paul DelRe
  • 4,003
  • 1
  • 24
  • 26
  • $hit, is not a class, its just a variable of type Object – mrN Apr 11 '11 at 14:23
  • I am not familiar with Zend, but it should work on any object from PHP's stdClass. I tested with: `$hit = new stdClass(); $hit->name = 'foo'; echo property_exists($hit, 'name') ? 't' : 'f'; > t` – Paul DelRe Apr 11 '11 at 14:33
  • 1
    It won't work correctly if the property does not exist in the first place but it is implemented using `__get` instead. – Jon Apr 11 '11 at 14:52
  • @Jon I see. Thanks for the insight into this Zend class. – Paul DelRe Apr 11 '11 at 15:48
0

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

stevevls
  • 10,675
  • 1
  • 45
  • 50
0
# Verify if exists
$hits = $index->find('id_field:100');
if (isset($hits[0])) { echo 'true'; } else { echo 'false'; }
Jérôme Verstrynge
  • 57,710
  • 92
  • 283
  • 453
Brynner Ferreira
  • 1,527
  • 1
  • 21
  • 21
0

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>';
?>
ZagNut
  • 1,431
  • 15
  • 20