1

これが私が実行しているコードです。

基本的に、私はデータをスクレイプし、それらを単純な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を返すのはなぜですか?

4

5 に答える 5

5

それは確かにスコーピングの問題です。これは機能しません:

$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ないでください。本当に正当な理由がない限り、参照を渡さないでください。

于 2012-07-27T19:03:26.903 に答える
3

いいえ。 Variable Scopeの概念を誤解しています。

次の点を考慮してください。

$foo = "bar";

function change_foo($new_foo) {
    $foo = $new_foo;
}

change_foo("New Foo!");
echo $foo;

この場合の出力は、依然として"bar". これは、 の$foo内部が関数スコープchange_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まったく変更していることに気付かなかったでしょう。

于 2012-07-27T19:11:23.543 に答える
2

私の現在の言語理解では、 $parsedItems オブジェクトは関数の外で宣言されているので、正しく追加すべきではないでしょうか?

いいえ、C# と同じように、関数に渡す必要があります。

于 2012-07-27T18:55:03.437 に答える
0

追加することもできますが

global $parsedNews

あなたの関数宣言の中で。アイテムを変更し、変更された値をグローバルスコープに反映させる必要がある場合は、参照によってアイテムを関数に渡す方が良いコーディング方法だと思います。したがって、関数の署名をこれに変更するだけです

function parse_page_for_news ($page, &$parsedNews)
于 2012-07-27T18:55:19.250 に答える
-6

Newsオブジェクトにはブラケットがありません。次のようなコンストラクタである必要があります。

$newItem = new News();

また、Newsクラスにはコンストラクターが必要です。宣言しないことで、デフォルトのコンストラクターが自動的に与えられるかどうかはわかりません(つまり、引数なし)

于 2012-07-27T18:51:24.780 に答える