【问题标题】:Check if a field/propertry exists in a variable of type object检查对象类型的变量中是否存在字段/属性
【发布时间】:2011-04-11 13:53:44
【问题描述】:

我正在使用 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 -&gt; name等内容

【问题讨论】:

  • 是跳过该行还是出现 PHP 错误?你似乎优柔寡断。
  • 当然错误Fatal error: Uncaught exception 'Zend_Search_Lucene_Exception' with message 'Field name "name" not found in document
  • 我刚刚解决了这个问题,但请记住,如果您没有给出确切的错误消息,我将永远无法做到。今后,请在提问时发布所有相关消息。不要让人们猜测,这会让更难获得帮助。

标签: php object zend-search-lucene


【解决方案1】:

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

在您的循环中,$hitZend_Search_Lucene_Search_QueryHit 类的对象。当您编写表达式$hit-&gt;name 时,对象调用magic __get function 为您提供一个名为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 中的一个错误,并且可能会提交一份报告,要求在它应该是的类型上适当地实现 __isset 魔术方法。

【讨论】:

  • getFieldNames 不返回关联数组。我已经更正了你的答案。
  • 谢谢,乔恩。 @Starx,我不知道你也知道 Zend Framework。
  • @mrN,我也是这方面的新手。但是,在你发帖之前先试试我。 :P
【解决方案2】:

你可以试试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>';
}

【讨论】:

  • $hit,不是一个类,它只是一个 Object 类型的变量
  • 我不熟悉 Zend,但它应该适用于 PHP 的 stdClass 中的任何对象。我测试过:$hit = new stdClass(); $hit-&gt;name = 'foo'; echo property_exists($hit, 'name') ? 't' : 'f'; &gt; t
  • 如果属性一开始不存在,它就不能正常工作,而是使用__get来实现。
  • @Jon 我明白了。感谢您深入了解这个 Zend 类。
【解决方案3】:

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

$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

【讨论】:

    【解决方案4】:
    # Verify if exists
    $hits = $index->find('id_field:100');
    if (isset($hits[0])) { echo 'true'; } else { echo 'false'; }
    

    【讨论】:

      【解决方案5】:

      如果您只是先将对象转换为数组,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>';
      ?>
      

      【讨论】:

        猜你喜欢
        • 2011-01-13
        • 2013-01-03
        • 1970-01-01
        • 1970-01-01
        • 2012-06-17
        • 2018-01-01
        • 2020-11-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多