サポート » 使い方全般 » 外部のRSSを複数取得する方法

  • 解決済 kazuxtaka

    (@kazuxtaka)


    外部のRSSを複数取得し、新着情報一覧を表示しています。
    いつからか不明なのですが、下記エラー文が表示され、一覧が表示されなくなってしまいました。
    以前、WP3.4.1からWP4.7.5へバージョンアップをいたしました。
    バージョンアップが原因なのかわかりませんが、以前はでていませんでした。

    Fatal error: Call to undefined method WP_Error::get_item_quantity() in …

    初めに作成した者が別の者で、独自のテーマのため、原因などがわからず困っております。
    RSSの表示のコードは以下です。

    <?php
    
    function sort_news_by_date($a, $b){
    	if($a->date == $b->date) return 0;
    	return ($a->date < $b->date) ? 1 : -1;
    }
    
    function get_news_from_feeds($feed_urls) {
    	$news_itmes = array();
    	$maxnum = 5;
    
    	// Get Feeds
    	include_once(ABSPATH . WPINC .'/feed.php');
    
    	foreach($feed_urls as $site => $url) {
    		$feed = fetch_feed($url);
    		$maxitems = $feed->get_item_quantity($maxnum);
    		$feed_items = $feed->get_items(0, $maxitems);
    		foreach($feed_items as $item) {
    			$news_item = new stdClass();
    			$news_item->site  = (string) $site;
    			$news_item->date  = strtotime($item->get_date('Y-m-d H:i:s'));
    			$news_item->link  = $item->get_permalink();
    			$news_item->title = $item->get_title();
    			$news_items[] = $news_item;
    			unset($news_item);
    		}
    	}
    
    	// Get Posts
    	$post_items = get_posts("numberposts={$maxnum}") ;
    	foreach($post_items as $post) {
    		$news_item = new stdClass();
    		$news_item->site  ='post';
    		$news_item->date  = strtotime($post->post_date);
    		$news_item->link  = get_permalink($post->ID);
    		$news_item->title = $post->post_title;
    		$news_items[] = $news_item;
    		unset($news_item);
    	}
    	// Sort
      if(!empty($news_items)) {
      	usort($news_items, "sort_news_by_date");
      }
    	// return
    	return $news_items;
    }
    
    // -----------------------------------------------
    
    $html = array();
    $feed_urls = array(
        'A' => 'ドメイン/A?feed=rss2&cat=3',
        'B' => 'ドメイン/B?feed=rss2&cat=3',
        'C' => 'ドメイン/C?cat=3&feed=rss2'
    );
    
    $site_names = array(
      'C' => 'Cカテゴリー',
      'A' => 'Aカテゴリー',
      'B' => 'Bカテゴリー'
    );
    
    $news_items = get_news_from_feeds( $feed_urls );
    $C_items = get_news_from_feeds( array( 'C' => $feed_urls['C'] ) );
    $B_items = get_news_from_feeds( array( 'B' => $feed_urls['B'] ) );
    $A_items = get_news_from_feeds( array( 'A' => $feed_urls['A'] ) );
    
    $output_num = 0;
    foreach($news_items as $item) {
    
    	// max number
    	if($output_num == 6) break;
        //if ( $item->site !== 'post' ) continue;
    	$output_num++;
    
    	$html[] ='<dt>'.date('Y', $item->date).'.'. date('m.d', $item->date) .'<img src="'.get_bloginfo('template_directory').'/画像/icon_'.$item->site.'.png" alt="" width="45" height="20" /></dt>';
    	$html[] = ($output_num === 1) ? '<dd class="first">' : '<dd>';
      $html[] ='<a href="'. esc_attr($item->link) .'">'. esc_attr($item->title) .'</a>';
    	$html[] ='</dd>';
    }
    
    $output_num = 0;
    foreach($C_items as $item) {
    	// max number
    	if($output_num == 5) break;
        if ( $item->site === 'post' ) continue;
    	$output_num++;
    
    	$html_C[] ='<dt>'.date('Y', $item->date).'.'. date('m.d', $item->date) .'<img src="'.get_bloginfo('template_directory').'/画像/icon_'.$item->site.'.png" alt="" width="45" height="20" /></dt>';
    	$html_C[] = ($output_num === 1) ? '<dd class="first">' : '<dd>';
      $html_C[] ='<a href="'. esc_attr($item->link) .'">'. esc_attr($item->title) .'</a>';
    	$html_C[] ='</dd>';
    }
    
    $output_num = 0;
    foreach($B_items as $item) {
    	// max number
    	if($output_num == 5) break;
        if ( $item->site === 'post' ) continue;
    	$output_num++;
    
    	$html_B[] ='<dt>'.date('Y', $item->date).'.'. date('m.d', $item->date) .'<img src="'.get_bloginfo('template_directory').'/画像/icon_'.$item->site.'.png" alt="" width="45" height="20" /></dt>';
    	$html_B[] = ($output_num === 1) ? '<dd class="first">' : '<dd>';
      $html_B[] ='<a href="'. esc_attr($item->link) .'">'. esc_attr($item->title) .'</a>';
    	$html_B[] ='</dd>';
    }
    
    $output_num = 0;
    foreach($A_items as $item) {
    	// max number
    	if($output_num == 5) break;
        if ( $item->site === 'post' ) continue;
    	$output_num++;
    	$html_A[] ='<dt>'.date('Y', $item->date).'.'. date('m.d', $item->date) .'<img src="'.get_bloginfo('template_directory').'/画像/icon_'.$item->site.'.png" alt="" width="45" height="20" /></dt>';
    	$html_A[] = ($output_num === 1) ? '<dd class="first">' : '<dd>';
      $html_A[] ='<a href="'. esc_attr($item->link) .'">'. esc_attr($item->title) .'</a>';
    	$html_A[] ='</dd>';
    }
    ?>
    
    <dl id="news_all">
    <?php echo implode("\n", $html) ?>
    </dl>
    <dl id="news_A">
    <?php echo implode("\n", $html_A) ?>
    </dl>
    <dl id="news_C">
    <?php echo implode("\n", $html_C) ?>
    </dl>
    <dl id="news_B">
    <?php echo implode("\n", $html_B) ?>
    </dl>

    恐れ入りますが、アドバイスなど頂けると幸いです。

10件の返信を表示中 - 1 - 10件目 (全10件中)
  • CG

    (@du-bist-der-lenz)

    他の思い当たりがなくて、バージョンアップが原因とするならば、バージョンアップする以前と比べてはどうでしょうか

    Colorful-life.

    (@colorfullifeinfo)

    こんにちは

    ご提示なさったコード全てに目を通した訳では無いのですが、
    エラーの原因としては get_news_from_feeds() 関数内でフィードの取得が失敗した時に起こっているのでは無いでしょうか?

    fetch_feed() で取得に失敗したときに WP_Error が返ってきていると思いますので、

    $feed = fetch_feed($url);
    if ( true === is_wp_error( $feed ) || true === empty( $feed )  )
    	continue;

    などとして、失敗時にスキップするようにしてみるとどうなりますか?

    [追記]
    あと、「いつからか不明」との事ですので、取得するフィードのURLが正しい物か(実際に存在しているか)確認した方が良いかもしれませんね

    • この返信は2 年、 3 ヶ月前に  Colorful-life. さんが編集しました。理由: タイポ
    • この返信は2 年、 3 ヶ月前に  Colorful-life. さんが編集しました。理由: 追記

    早速、ご返信ありがとうございます。

    CG 様
    テーマファイル自体は触っておらず、バージョンアップを行ったのみになります。
    となるとバージョンアップで以前はそのまま使えた書き方が使えなくなってしまったなどがあるのでしょうか。

    Colorful-life. 様
    お送りいただいたif文を追加いたしましたら、「ALL」について出力がされるようになりました。
    ABCについては、
    Warning: implode() [function.implode]: Invalid arguments passed in
    と警告文が出ており、Aなら

    <dl id="news_A">
    <?php echo implode("\n", $html_A) ?> //←ここ
    </dl>

    が該当箇所のようです。

    ここでも記事のデータが取得できていないのでしょうか。
    よろしくお願いいたします。

    【追記】
    Colorful-life. 様
    取得しているfeedのURLですが、こちらは記載のもので記事の情報がざっと表示されるページが確認できるものを指定しております。
    指定しているURLドメイン/A?feed=ss2を表示させるとドメイン/A/feed/に遷移してしまうのですが、
    この遷移したURLだと別のエラーが表示されました。
    Fatal error: Call to a member function get_items() on a non-object in …

    • この返信は2 年、 3 ヶ月前に  kazuxtaka さんが編集しました。
    Colorful-life.

    (@colorfullifeinfo)

    Warning: implode() [function.implode]: Invalid arguments passed in

    implode() の第二引数が配列では無いからですよね
    (Aの場合なら)$html_A が未定義なのでエラーが出ているのでは無いでしょうか?

    エラーが出なくなれば良いだけなら、

    $output_num = 0;
    foreach($A_items as $item) {

    の部分を

    $output_num = 0;
    $html_A = [];
    foreach($A_items as $item) {

    とすれば良いと思います。

    ちなみに、当方の環境( WordPress 4.7.5 、 PHP 7.1.5 )では fetch_feed() も問題無く動作しており、
    その返り値(SimplePieクラスのインスタンス)に対したメソッド get_items() なども動作していますので、
    $feed = fetch_feed($url); が失敗している原因を特定する必要がありそうですね

    例えば、RSSへのリクエストに対して、ユーザーエージェントやIPなどでブロックされている等は考えられませんか?

    Colorful-life. 様
    引き続きご返信ありがとうございます。
    phpのバージョンが使用サーバー(Bizメール)で5.6だったためか、
    []が使えずarray()に置き換えれば使えるようでしたので、
    書き換えを行ったところエラーは表示されなくなりました。

    特別、ブロックするような設定は行っていないかと思います。
    調べておりましたら下記サイトでエラーの有無の確認ができ、
    記事の中身にエラーが見つかりました。
    ▽W3C Feed Validation Service
    https://validator.w3.org/feed/

    WP4.4以降からビジュアルエディタでの挿入画像にsrcsetが挿入されるようで、
    それが使用できないようなエラーがでていたため、自動で挿入されないように設定を修正しました。

    残っているエラー(推奨?)が下記になります。

    Self reference doesn't match document location
    <atom:link href="feedURL" rel="self" type="application/rss+xml" />

    上記について、他のサイトで同じエラーがでているものでも取得できるものはできているようで、
    もう少し調べてみようと思います。

    • この返信は2 年、 3 ヶ月前に  kazuxtaka さんが編集しました。
    Colorful-life.

    (@colorfullifeinfo)

    的外れな指摘で失礼しました

    取得するRSSの文法の問題かもしれない、という事なのですね

    RSS取得失敗の際にWP_Error のメッセージなど表示させてみると調査の助けになるかもしれません、ご参考まで。

    例えば、こんな感じで…

    $feed = fetch_feed($url);
    if ( true === empty( $feed ) )
    	continue;
    	
    if ( true === is_wp_error( $feed ) ) {
    	var_dump( $feed->get_error_messages() );
    	continue;
    }

    Colorful-life. 様

    ご返信ありがとうございます。
    とんでもないです。
    何から調べていいものかと困り果てておりましたので、助かっております。
    また、エラーメッセージの表示方法のご教示ありがとうございます。
    頂いたコードを参考に調べて見ようと思います。

    Colorful-life. 様に教えていただいたエラーメッセージの表示方法から解決できましたことご報告させていただきます。

    エラーメッセージを表示させましたところ、
    「WP HTTP ERROR:有効なURLではありません」
    とメッセージが表示され、RSSのURLに問題があったようです。

    最終的なコードを比較したところfeedの手前に/があるかないかが原因でした。

    $feed_urls = array(
        'A' => 'ドメイン/A?feed=rss2&cat=3',
        'B' => 'ドメイン/B?feed=rss2&cat=3',
        'C' => 'ドメイン/C?cat=3&feed=rss2'
    );

    $feed_urls = array(
        'A' => 'ドメイン/A/?cat=3&feed=rss2',
        'B' => 'ドメイン/B/?cat=3&feed=rss2',
        'C' => 'ドメイン/C/?cat=3&feed=rss2'
    );

    (catとfeedの順番がバラバラだったのでまとめてあります)

    /のある無しでどう変わってくるのか、調べていくとして、
    こちらのエラーの件については解決とさせていただきます。
    アドバイスをくださったCG 様、Colorful-life. 様ありがとうございました。

    CG

    (@du-bist-der-lenz)

    /のある無しでどう変わってくるのか、調べていくと理解も深まります。
    スラッシュがない場合は、そのものを探すだけですから、ドメインの下にAのファイルがなければ、ページが存在しないの「404エラー」を返します。
    これは、WordPressの設定画面で、サイトのアドレスを指定するときも異なる挙動をしますので、意識的に使い分けましょう。

    CG 様
    /の有無について、ご返信ありがとうございます。
    通常の構造であれば/の中身がディレクトリ、/がなければファイルを探すようなものと理解しているのですが、Wordpressのディレクトリやファイルの構造の理解が甘い部分がございました。
    /の有無による挙動の違いについても、調べて試して理解を深めていこうと思います。

10件の返信を表示中 - 1 - 10件目 (全10件中)
  • トピック「外部のRSSを複数取得する方法」には新たに返信することはできません。