【问题标题】:Adding object to array, displays a count of 0将对象添加到数组,显示计数为 0
【发布时间】:2012-07-26 11:49:29
【问题描述】:

这是我正在运行的代码。

基本上我会抓取数据,并将它们放入简单的 POCO 类中。在循环结束时,我想将 $newItem 对象添加到 $parsedItems 数组中。我是 PHP 新手,这可能是范围问题吗?

<h1>Scraper Noticias</h1>

<?php

include('simple_html_dom.php');

class News {
    var $image;
    var $fechanoticia;
    var $title;
    var $description;
    var $sourceurl;

    function get_image( ) {
        return $this->image;
    }

    function set_image ($new_image) {
        $this->image = $new_image;
    }

    function get_fechanoticia( ) {
        return $this->fechanoticia;
    }

    function set_fechanoticia ($new_fechanoticia) {
        $this->fechanoticia = $new_fechanoticia;
    }

    function get_title( ) {
        return $this->title;
    }

    function set_title ($new_title) {
        $this->title = $new_title;
    }

    function get_description( ) {
        return $this->description;
    }

    function set_description ($new_description) {
        $this->description = $new_description;
    }

    function get_sourceurl( ) {
        return $this->sourceurl;
    }

    function set_sourceurl ($new_sourceurl) {
        $this->sourceurl = $new_sourceurl;
    }
}

// Create DOM from URL or file
$initialPage = file_get_html('http://www.uvm.cl/noticias_mas.shtml');


// Declare variable to hold all parsed news items.
$parsedNews = array();

// Since the University blog page has 262 pages, we'll iterate through that.
for ($i = 2; $i <= 5; $i++) {
    $url = "http://www.uvm.cl/noticias_mas.shtml?AA_SL_Session=34499aef1fc7a296fb666dcc7b9d8d05&scrl=1&scr_scr_Go=" . $i;
    $page = file_get_html($url);
    parse_page_for_news($page);
}

echo "<h1>Final Count:" . count($parsedNews) . "</h1>";

// Function receives an HTML Dom object, and the library works against that single HTML object.
function parse_page_for_news ($page) {

    foreach($page->find('#cont2 p') as $element) {

        $newItem = new News;

        // Parse the news item's thumbnail image.
        foreach ($element->find('img') as $image) {
            $newItem->set_image($image->src);
            //echo $newItem->get_image() . "<br />";
        }

        // Parse the news item's post date.
        foreach ($element->find('span.fechanoticia') as $fecha) {
            $newItem->set_fechanoticia($fecha->innertext);
            //echo $newItem->get_fechanoticia() . "<br />";
        }

        // Parse the news item's title.
        foreach ($element->find('a') as $title) {
            $newItem->set_title($title->innertext);
            //echo $newItem->get_title() . "<br />";
        }

        // Parse the news item's source URL link.
        foreach ($element->find('a') as $sourceurl) {
            $newItem->set_sourceurl("http://www.uvm.cl/" . $sourceurl->href);
        }

        // Parse the news items' description text.
        foreach ($element->find('a') as $link) {
            $link->outertext = '';
        }

        foreach ($element->find('span') as $link) {
            $link->outertext = '';
        }

        foreach ($element->find('img') as $link) {
            $link->outertext = '';
        }

        $newItem->set_description($element->innertext);

        // Add the newly formed NewsItem to the $parsedNews object.
        $parsedNews[] = $newItem;

        print_r($newItem);
        echo "<br /><br /><br />";

    }
} 

?>

在我目前对该语言的理解中,由于$parsedItems对象是在函数之外声明的,不应该正确添加吗?

为什么我的 count() 调用会返回 0,就好像它没有对象一样?

【问题讨论】:

  • 您的意思可能是$parsedNews。您的代码中没有 $parsedItems
  • 顺便说一句,如果您仅将 setter 和 getter 用作 POCO-ish 属性,则无需手动编写它们。 PHP 有所谓的“魔术方法”,当有人试图访问目标代码时,它会动态拦截。看这里:stackoverflow.com/questions/6550550/…

标签: php arrays scope


【解决方案1】:

您的News 对象没有括号。它应该是一个构造函数,像这样:

$newItem = new News();

另外,您的News 类需要一个构造函数。我不确定如果不声明一个,它会自动被赋予一个默认构造函数(即不带任何参数)

【讨论】:

  • 如果您不打算将参数传递给构造函数,或者如果构造函数具有可以使用的默认值,则不需要括号。
  • 对象实例化不需要括号
  • 另外,回复:您的编辑 - 该类也不严格需要构造函数。
  • 我修正了错别字,但仅供参考,这个答案不正确。此外,为了解决您在“答案”中提出的问题,没有构造函数的类只是......没有构造函数。没有一个“默认”,也没有一个类需要一个。
【解决方案2】:

以我目前对该语言的理解,既然 $parsedItems 对象是在函数外部声明的,不应该正确添加它吗?

不,您需要将它传递给函数,就像使用 C# 一样。

【讨论】:

    【解决方案3】:

    虽然你可以添加

    global $parsedNews
    

    在你的函数声明中。如果您需要能够修改它并将修改后的值反映在全局范围中,我认为通过引用将项目传递给函数是更好的编码实践。所以你可以简单地把你的函数签名改成这个

    function parse_page_for_news ($page, &$parsedNews)
    

    【讨论】:

    • 谢谢,这两个选项都有效。在这种情况下,我将把数组作为函数参数而不是全局变量传递。
    • 是的,不要使用全局变量。
    • 全局变量,不好。学习如何正确编码,无价之宝。
    【解决方案4】:

    这确实是一个范围界定问题。这不起作用:

    $foo= array();
    
    function bar()
    {
        $foo[] = 'baz';
    }
    
    bar();
    var_dump($foo); // will output an empty array
    

    你想要做的是:

    $parsedNews = array();
    
    // loop through the items as you are doing now
    for ($i = 2; $i <= 5; $i++) {
        $url = "http://www.uvm.cl/noticias_mas.shtml?AA_SL_Session=34499aef1fc7a296fb666dcc7b9d8d05&scrl=1&scr_scr_Go=" . $i;
        $page = file_get_html($url);
        $newItems = parse_page_for_news($page);
    
        $parsedNews = array_merge($parsedNews, $newItems);
    }
    

    parse_page_for_news 函数在循环结束后返回parsedNews

    return $parsedNews;
    

    请永远不要使用 global 关键字,除非您有充分的理由,否则请不要通过引用传递。

    【讨论】:

      【解决方案5】:

      没有。您误解了 Variable Scope 的概念。

      考虑以下几点:

      $foo = "bar";
      
      function change_foo($new_foo) {
          $foo = $new_foo;
      }
      
      change_foo("New Foo!");
      echo $foo;
      

      在这种情况下,输出仍然是"bar"。这是因为change_foo() 内的$foo 包含在函数范围 内。

      但是,如果我们要这样做(正确的方法):

      $foo = "bar";
      
      function change_foo($new_foo) {
          $foo = $new_foo;
          return $foo;
      }
      
      $foo = change_foo("New Foo!");
      echo $foo;
      

      结果确实是New Foo!

      另一种(不太推荐的)方法如下:

      $foo = "bar";
      
      function change_foo(&$old_foo, $new_foo) {
          $old_foo = $new_foo;
      }
      
      change_foo($foo, "New Foo!");
      echo $foo;
      

      之所以不推荐这样做,是因为从代码中看不出$foo被改变了(当然,因为我给函数起的正确名称,看起来已经够明显了)。

      这样做最糟糕的方法是将$foo 移动到全局状态。

      $foo = "bar";
      
      function change_foo($new_foo) {
          global $foo;
          $foo = $new_foo;
      }
      
      change_foo("New Foo!");
      echo $foo;
      

      通过全球化$foo 变量,函数中的任何人和每个人都可以访问和更改它。如果函数的名称不是那么明显,我们永远不会知道它改变了$foo 的值!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-01-13
        • 2018-09-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多