前の記事では「PHP8で何が変わったか」と「error.logの読み方」を紹介しました。
この記事では、実際に発生したWarning 5パターンを、before/afterのコードつきで解説します。
PHP7→PHP8に上げたらerror.logが増えた。まず何をすべきか【WordPress】
パターン1:$post->post_name on null
エラーメッセージ
PHP Warning: Attempt to read property "post_name" on null in header.php on line 229
原因
グローバル変数 $post は、投稿・固定ページを表示しているときはWordPressが自動的にセットしてくれます。ところが、アーカイブページ・検索結果ページ・404ページでは $post が null になることがあります。
PHP7.xでは null のプロパティへのアクセスがNoticeで済んでいましたが、PHP8.xではWarningになります。
Before(よく書かれているコード)
header.php や index.php のように、bodyタグのid属性やスラッグ取得で使われていることが多いです。
// header.php
<body id='<?php echo esc_attr($post->post_name); ?>'>
// index.php
$slug = $post->post_name;
After(修正後)
isset() で $post->post_name が存在するか確認してから使います。
// header.php
<body id='<?php echo esc_attr(isset($post->post_name) ? $post->post_name : ''); ?>'>
// index.php
$slug = isset($post->post_name) ? $post->post_name : '';
ポイント
$post 自体が null のとき、$post->post_name にアクセスしようとするとWarningが出ます。isset($post) だけでなく isset($post->post_name) と書くことで、$post が null の場合も含めて安全にチェックできます。
パターン2:get_post_meta() の戻り値に ++ をしたときのWarning
エラーメッセージ
PHP Deprecated: Increment on type bool in functions.php on line 1034
原因
ビューカウント(閲覧数)の実装でよく使われるパターンです。get_post_meta() は値が存在しない場合に false を返します。
PHP7.xではbool型に ++ しても動作していましたが、PHP8.3以降では Deprecated(非推奨)の警告が出ます。
Before(よく書かれているコード)
$post_views_count = get_post_meta($post_id, $custom_key, true);
if ($post_views_count === '') {
delete_post_meta($post_id, $custom_key);
add_post_meta($post_id, $custom_key, '0');
} else {
$post_views_count++; // falseが来たときに bool への++ になる
update_post_meta($post_id, $custom_key, $post_views_count);
}
問題点
get_post_meta() の戻り値は string | false です。第3引数を true にした場合、メタデータが存在しないと false が返ります。=== '' のチェックだけでは false を捕捉できないため、else ブロックに false が流れ込んで false++ になります。
After(修正後)
$post_views_count = get_post_meta($post_id, $custom_key, true);
if ($post_views_count === '' || $post_views_count === false) {
// メタデータが存在しない or 空のとき → 初回閲覧なので1をセット
delete_post_meta($post_id, $custom_key);
add_post_meta($post_id, $custom_key, '1');
} else {
// 明示的に (int) キャストしてから +1 する
$post_views_count = (int) $post_views_count + 1;
update_post_meta($post_id, $custom_key, (string) $post_views_count);
}
ポイント
falseチェックを=== ''と一緒に追加する(int)で明示的に整数にキャストしてから計算する- 初期値は
'0'より'1'が正しい(初回閲覧時点でカウント1)
パターン3:foreach() に null を渡すWarning
エラーメッセージ
PHP Warning: foreach() argument must be of type array|object, null given in header.php on line 677
原因
グローバル変数を foreach しているコードで、その変数が別のテーマから複製してきた際に定義されていないケースです。
たとえば テーマの functions.php には $global_session_params という変数が定義されていても、それをコピー元にして作った テーマでは定義が漏れていた、というケース。
Before(よく書かれているコード)
// header.php
global $global_session_params;
foreach ($global_session_params as $key => $value) {
$_SESSION[$key] = $value;
}
$global_session_params が null の場合、PHP8ではWarningが出ます。
After(修正後)
global $global_session_params;
if (is_array($global_session_params)) {
foreach ($global_session_params as $key => $value) {
$_SESSION[$key] = $value;
}
}
ポイント
is_array() で確認してから foreach する習慣をつけると、グローバル変数が未定義の場合でも安全に動作します。
テーマ複製時にグローバル変数の定義が漏れることは非常によくあります。定義を追加するよりも、使用側で防御的チェックをするほうが他のテーマに使い回せて安全です。
パターン4:存在しない $_GET キーへのアクセス
エラーメッセージ
PHP Warning: Undefined array key "post" in functions.php on line 976
原因
WordPress管理画面では、URL上のパラメータがページによって変わります。
たとえば投稿一覧から投稿を開くURLは /wp-admin/post.php?post=123&action=edit ですが、新規投稿作成のURLは /wp-admin/post-new.php で post パラメータがありません。
$_GET['post'] を直接参照しているコードは、post パラメータが存在しないページでWarningが出ます。
Before(よく書かれているコード)
function disable_visual_editor_in_page($args) {
$post_id = $_GET['post']; // 新規投稿画面では存在しない
$post_type = get_post_type($post_id);
if ($post_type === 'page') {
$args['tinymce'] = false;
}
return $args;
}
add_filter('wp_editor_settings', 'disable_visual_editor_in_page');
After(修正後)
function disable_visual_editor_in_page($args) {
if (!isset($_GET['post'])) {
return $args; // postパラメータがないときは何もせず返す
}
$post_id = $_GET['post'];
$post_type = get_post_type($post_id);
if ($post_type === 'page') {
$args['tinymce'] = false;
}
return $args;
}
add_filter('wp_editor_settings', 'disable_visual_editor_in_page');
ポイント
$_GET や $_POST のキーにアクセスする前は、必ず isset() で存在確認をします。「このページでは必ずあるはず」という思い込みがWarningの原因になります。
パターン5:if-elseif-else の全分岐で変数が定義されていない
エラーメッセージ
PHP Warning: Undefined variable $pbndSml in parts/pagecover/pageband-elf.php on line 222
原因
if-elseif-else で変数を定義する際、最後の else ブロックで変数の定義が漏れているケースです。
Before(よく書かれているコード)
if ($page_band_style === 'large') {
$pbndSml = 'pbnd-lg';
} elseif ($page_band_style === 'medium') {
$pbndSml = 'pbnd-md';
}
// else ブロックがない、または else の中で $pbndSml を定義していない
// 後続の処理
echo '<div class="' . $pbndSml . '">'; // $pbndSml が未定義の場合にWarning
After(修正後)
if ($page_band_style === 'large') {
$pbndSml = 'pbnd-lg';
} elseif ($page_band_style === 'medium') {
$pbndSml = 'pbnd-md';
} else {
$pbndSml = ''; // 主要な分岐で必ず定義する
}
echo '<div class="' . $pbndSml . '">';
ポイント
if-elseif で条件を列挙するとき、最後の else を忘れやすいです。変数を使う前に必ず初期化されているか確認しましょう。
テンプレートファイルの先頭で $pbndSml = ''; と事前に初期化しておく方法もあります。
// ファイルの先頭で初期化しておく方法
$pbndSml = '';
if ($page_band_style === 'large') {
$pbndSml = 'pbnd-lg';
} elseif ($page_band_style === 'medium') {
$pbndSml = 'pbnd-md';
}
どちらの書き方でも問題ありませんが、「使う前に必ず定義済みの状態にする」という意識が大切です。
まとめ
| パターン | 原因 | 対処 |
|---|---|---|
$post->post_name on null |
アーカイブ等で$postがnull |
isset($post->post_name) チェック |
| bool increment | get_post_meta()がfalseを返す |
falseチェック + (int)キャスト |
foreach() null |
グローバル変数の定義漏れ | is_array() チェック |
$_GET undefined key |
URLパラメータが存在しないページ | isset() チェック |
| 変数未定義 | 全分岐での定義漏れ | elseブロックでも初期化 |
いずれも「存在確認をしてから使う」「型を確認してから演算する」というシンプルな対処です。
関連記事
WordPressテーマのFatal Errorとエラーの連鎖構造を直す【PHP7→PHP8移行】
PHP7→PHP8に上げたらerror.logが増えた。まず何をすべきか【WordPress】
WordPress $post変数のnullエラーを完全解決!error_logを綺麗にする実践的修正ガイド

