ブログのテーマのバグ発見

先週、管理しているブログサーバーのエラーログをチェックしたところ、大量のPHPのワーニングが出ているのに気がつきました。

こんな感じのもがログファイルを埋め尽くしています。


 PHP Warning:  Invalid argument supplied for foreach() in 
(WordPressのあるパス)/wp-content/themes/(自作テーマ?)/include/modal.php on line 7

メッセージに記載してあったmodal.php の該当する箇所は、次のようなコードでした。

$terms = get_the_terms($post->ID, 'date'); 
$t_slug=''; 
foreach ($terms as $term) { 
	$term_name = $term->slug; 
	$t_slug = $t_slug.'d'.$term_name.' ';
}; 
$t_slug = substr($t_slug, 0, -1); 
echo $t_slug;

WordPress 組み込みの関数 get_the_terms() を受け取ったデータを表示しています。どうも表示中の投稿と同じタームの情報を表示するのに使う関数らしいのですが、実はこの get_the_terms()、失敗した場合は FALSE を返します。

表示しているページによっては、FALSE になるのでしょう。というか、トップページだったら、必ず FALSE になっていると思います。

get_the_terms() のリファレンスには、ちゃんと失敗したら、ということが書いてあるのですが、これを書いた人は、ケアする必要を感じなかったのでしょうね。一応、ちゃんと動くし。

サーバーを管理する側としては、こんなワーニングで重要なメッセージを見落とすと困るし、余計なDISKを使っていまう、何も考えずに、is_array() 文で条件分岐して、FALSE だったら何も表示
しないようにコードを修正しました。
今は、このワーニングは出てません。

$terms = get_the_terms($post->ID, 'date'); 
$t_slug=''; 
if( is_array($terms) ) {
	foreach($terms as $term) { 
		$term_name = $term->slug; 
		$t_slug = $t_slug.'d'.$term_name.' '; 
	}; 
	$t_slug = substr($t_slug, 0, -1); 
}
echo $t_slug; 

これは、foreach() の第1引数は、配列かオブジェクトでなければならない、という仕様があり、FALSE は配列でもオブジェクトでもないということで、ワーニングが出ています。なので、配列でなかったら何も表示しないようにしました。

でも、「FALSE」というたった1つだけの配列と見なせばできて当然、という考えもあります。

ということで、こんな書き方もできるのだそうです。

$terms = get_the_terms($post->ID, 'date'); 
$t_slug=''; 
foreach ((array) $terms as $term) { 
	$term_name = $term->slug; 
	$t_slug = $t_slug.'d'.$term_name.' ';
}; 
$t_slug = substr($t_slug, 0, -1); 
echo $t_slug;

C言語でよくやるキャスティングですね。char 型の変数なんだけど、int の変数といっしょに計算させたいので、この計算だけは int として扱いますみたいな。
個人的には、is_array() で判定させて、確実に何も表示させないようにする、が正しいとは思いますが、問題無いみたいです。

is_array() は、私もすぐに思いついたのですが、(array) をつけるやり方はすぐには解らず、こちらを参考にさせてもらいました。

foreach文のエラーが出た時の対処方法

この記事の作者も教えてもらったようでう、元ねたはこちらだそうです。

PHPのforeach文でnullチェックなしでエラー回避

C言語のキャスティングは、20年以上前のよく書いていたころは使っていましたが、ここ10年
くらいはまったくやってません。すっかり忘れてました。幾つもの言語を使いこなして、それぞれの
いい点をうまく使っていく、というのがカッコイイな、と改めて思っています。