我使用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(" » ",$title);
$content .= '</h2>';
$content .= '<p>'.$this->content.'</p>';
$content .= '</div>';
}
如何检查$hit
中是否存在$hit -> name
等物质
您遇到的问题非常非常具体,与Zend_Lucene_Search
实现有关,而不是一般的字段/属性存在检查。
在循环中,$hit
是Zend_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(" » ",$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>';
?>