post-template.phpでWarning: count()が発生する根本原因と対処方法

PHP 7.2以降のWordPressでは、post-template.phpのcount処理でWarningが発生することがある。このような警告メッセージが発生する根本的な原因は、テーマ側やプラグイン側の実装の不備にある。

Warning: count(): Parameter must be an array or an object that implements Countable in /htdocs/wp/wp-includes/post-template.php on line 284

WordPress本体に問題があるわけではないため、安易にWordPress側のコアファイル(post-template.php)の修正は行わないよう注意されたい。

本記事では、この問題の根本原因と、それに対する有効な解決策について解説していく。

目次

エラーの原因

このエラーが発生する原因には、post-template.php284行目付近でcount($pages)という処理が行われていることが関係している。$pagesにはNULLがセットされることがあり、それがcount(NULL)という不正処理に繋がり、警告が発生してしまうのである。

/htdocs/wp/wp-includes/post-template.php
284| if ( $page > count( $pages ) ) // if the requested page doesn't exist
285|   $page = count( $pages ); // give them the highest numbered page that DOES exist
もともとcount(NULL)処理は0を返すだけの処理であったが、PHP 7.2以降はWarningによる警告メッセージが表示されるようになった。
冒頭のWarning: count(): Parameter must be an array or an object that implements Countableというのは「引数には配列型の値が必要である」という趣旨のメッセージであり、したがってPHP 7.2以降のcount関数は事実上、配列型とそれに類するCountableな値しか容認されないことになっている。

$pagesNULLがセットされてしまうケースとは、主に記事の本文を扱うthe_content関数やget_the_content関数をループ外で呼び出してしまった場合などである。

また、記事の抜粋を扱うthe_excerpt関数やget_the_excerpt関数、wp_trim_excerpt関数についても同様の問題を引き起こす場合がある。いずれの関数もget_the_contentに依存しているためである。

投稿(global $post)がきちんとセットアップされていない状況でget_the_contentが呼び出されると、$pagesが未定義の状態で読み取られてしまうことになるため、今回のようなエラーに繋がることになる。

実際にthe_contentやthe_titleなどの投稿関連の関数はループ内で使用されることが前提とされている。

対処方法

この警告は主に、投稿がセットされていない状態、とりわけループの外でthe_content関数やthe_excerpt関数が呼び出されてしまった際などに発生する。

そのため、それらの関数がきちんとループの内側で呼び出されていることを確認する必要がある。

the_content(); // このような場所では使えない

if ( have_posts() ) {
  while ( have_posts() ) {
    the_post();    // この事前処理も必須(ここで初めてループに入る)
    the_content(); // OK
  }
}

また、テンプレート内でthe_post関数がきちんと呼び出されているかどうかも確認する必要がある。事前にthe_postを呼び出しておかないと$pagesは不定なままとなり、今回のようなエラーに繋がってしまう。

対応対象のファイルには、主に投稿ページ(single.php)や固定ページ(page.php)といった単一の投稿を扱うのもの等が想定される。

それらのファイル内でcontent系関数(the_content, get_the_content)の呼び出し処理が行われているはずなので、それらがループ内に置かれているかどうかを確認するとよい。

同様に、excerpt系関数(the_excerpt, get_the_excerpt, wp_trim_excerpt)の呼び出し処理やget_template_part('content', '');といった処理についても確認しておく。

ヘッダー周りの処理を自作している場合は、functions.php辺りを疑ってみるとよい。特にthe_excerpt等の投稿関連の関数は内部でget_the_contentを呼び出すことがあるため注意する。

第三者が開発したテーマやプラグインの側に問題があるケースもあるため、個人では対応できない場合もある。# 対処できない場合はエラーメッセージを非表示にするとよい

WordPressのコアファイル(post-template.php)を修正してはならない

WordPressのコアファイル(post-template.php)を修正する方法も広く知られているが、根本的な問題の解決には繋がらないため、そのような対応は勧められない。

/htdocs/wp/wp-includes/post-template.php
284| if ( !empty( $pages ) ) { // このような修正は行ってはならない
285|   if ( $page > count( $pages ) )
286|     $page = count( $pages );
287| }
288|
289| $content = $pages[$page - 1]; // 後続の処理にも矛盾が生じる

そもそも、コアファイルはWordPressのアップデート時に更新されてしまうため、毎回修正が必要になってしまうという問題もある。またコアファイルに対する独自の修正は、システム全体への影響が懸念されリスクも大きい。

対処できない場合はエラーメッセージを非表示にするとよい

今回の警告はテーマ側やプラグイン側に問題があるため、それぞれの開発者に機能の修正を依頼することがもっとも賢明な対応となる。

問題が解消されるまでは、エラーの非表示を行うなどして対処するとよい。

PHPのdisplay_errorserror_reportingを用いることで、警告メッセージを非表示ないし抑制することができる。

PHPのバージョンを下げる方法も考えられる

この問題は「PHP 7.2」以降のcount関数の仕様変更が関係しているため、PHPのバージョンを下げることによって、この問題に対処することも可能となっている。ただし推奨はされない。

誤ってPHPのバージョンを上げてしまった場合などであれば、本体を「PHP 7.2」より前のバージョンに戻すことで、この問題の対応を先延ばしにすることができる。少なくともサードパーティ製のテーマやプラグインの対応が済むまで、バージョンアップを保留することができる。

ただし、バージョンの差し戻しによって、これまで動いていた処理が動かなくなってしまう恐れもあるため、注意が必要である。特にWordPressをアップグレードした後や、プラグインを更新した後にPHPのバージョンを下げるような場合には、細心の注意が必要となる。

しかしもっとも有効な対応は、先程から紹介しているコードの見直しや、エラーメッセージの非表示による対応である。

広告