【WordPress】投稿に自動で公開終了する機能をつける

こんにちは、TANE-beエンジニアです。
WordPressには予約投稿を行える機能がありますが、公開終了日を設定する機能はありません。そこで今回はカスタムフィールドを使用して、自動で投稿を非表示にする方法をご紹介します。
また、今回は分かりやすいように、予約投稿も同じようにカスタムフィールドで設定していきます。※ 自動で非公開に切り替える方法ではないのでご注意ください
- WordPressで期間を決めて記事を投稿したい
- WordPressの投稿に、特定のタイミングで記事を表示しないようにする仕様を追加したい
カスタムフィールドによる日付設定欄の作成
今回は操作が分かりやすいAdvanced Custom Fields(ACF)のプラグインを使用して日時を指定するフィールドを作成します。
日時を正確に取得できれば、何を使用しても問題ありません。
※ 日時の指定ができない場合は、テキストフィールドを作成し、戻り値の形式を手入力しても同様の処理が行えます。
カスタムフィールドで、開始日時・終了日時の2つのフィールドを作成します。
フィールドラベルは分かりやすいように指定し(今回は「開始日時」「終了日時」としました)、フィールド名はそれぞれ「start」「finish」としておきます。フィールドタイプは、時間まで指定したいので「日時選択ツール」を選択します。
戻り値の形式は必ず「Y-m-d H:i:s」を選択してください。表示形式はどれでも問題ありませんが、今回は分かりやすいように同様の形式を選択しています。
投稿タイプを選択する箇所で、予約投稿・終了を行いたい投稿タイプを選択してください。
保存すると、投稿を入力する画面で日時の選択ができるようになります。
添付のようなフィールドで日時が入力できれば管理画面側の設定は完了です。次にテンプレート側を設定していきましょう。
設定した日時と現在の時刻を比べる条件分岐を設定
今回は投稿開始の予約、終了の予約のどちらも設定されている場合だけでなく、開始だけ、終了だけが設定されている場合も考慮してコードを作成していきます。
まずコードの全体像はこちらです。
一つずつ、コードの内容を確認していきましょう。
<?php if( have_posts() ): ?>
<ul>
<?php while( have_posts() ) : the_post(); ?>
<?php
// 現在時刻
$current = wp_date('Y-m-d H:i:s');
$currentDate = DateTime::createFromFormat('Y-m-d H:i:s', $current);
// カスタムフィールドの値を取得
$start = get_field('start');
$finish = get_field('finish');
// $startと$finishの両方が設定されている場合
if ($start && $finish) :
$startDate = DateTime::createFromFormat('Y-m-d H:i:s', $start);
$finishDate = DateTime::createFromFormat('Y-m-d H:i:s', $finish);
// 現在時刻が$startと$finishの間にある場合
if ($startDate <= $currentDate && $currentDate < $finishDate) :
?>
<li><?php the_title(); ?></li>
<?php endif; ?>
<!-- $startのみ設定されている場合 -->
<?php elseif ($start && !$finish) :
$startDate = DateTime::createFromFormat('Y-m-d H:i:s', $start);
// 現在時刻が$start以降であれば表示
if ($startDate <= $currentDate) :
?>
<li><?php the_title(); ?></li>
<?php endif; ?>
<!-- $finishのみ設定されている場合 -->
<?php elseif (!$start && $finish) :
$finishDate = DateTime::createFromFormat('Y-m-d H:i:s', $finish);
// 現在時刻が$finish前であれば表示
if ($currentDate < $finishDate) :
?>
<li><?php the_title(); ?></li>
<?php endif; ?>
<!-- $startも$finishも設定されていない場合 -->
<?php else : ?>
<li><?php the_title(); ?></li>
<?php endif; ?>
<?php endwhile; ?>
</ul>
<?php endif; ?>
現在日時の取得
まずは比較するために現在の日時を取得します。WordPressは日時を取得する関数が用意されているので、>wp_date()を使用します。
取得した値が文字列などだった場合にそなえて、日時として扱うフォーマットに変換します。共通の日時を扱うフォーマットにすることで、日時の比較などを正確に行えます。
$current = wp_date('Y-m-d H:i:s');
$currentDate = DateTime::createFromFormat('Y-m-d H:i:s', $current);
投稿開始・終了の日時を取得
開始日時、終了日時として管理画面側で入力した値を取得します。
$start = get_field('start');
$finish = get_field('finish');
そして、両方が入力されている場合、開始、終了が片方だけ入力されている場合を条件分岐します。取得した日時は、現在の日時と同じように日時を扱う共通のフォーマットに変換します。そして開始・終了日時が入力されていない場合は、通常どおり記事が吐き出される設定です。
まずは入力がある場合とない場合を条件分岐します。
<?php if ($start && $finish) :?>
<!-- 開始・終了日時の設定がある場合、さらにここで条件分岐をする(以下の条件分岐はここに入る) -->
<?php else : ?>
<!-- 特に設定されていない場合は通常通りここで処理する -->
<?php endif; ?>
それぞれの入力パターンを想定してさらに条件分岐します。
開始・終了日時が両方ある場合
<?php
$startDate = DateTime::createFromFormat('Y-m-d H:i:s', $start);
$finishDate = DateTime::createFromFormat('Y-m-d H:i:s', $finish);
// 現在時刻が$startと$finishの間にある場合
if ($startDate <= $currentDate && $currentDate < $finishDate) :
?>
<?php endif; ?>
開始だけ入力の場合
<?php
elseif ($start && !$finish) :
$startDate = DateTime::createFromFormat('Y-m-d H:i:s', $start);
// 現在時刻が$start以降であれば表示
if ($startDate <= $currentDate) :
?>
<?php endif; ?>
終了だけ入力の場合
<?php
elseif (!$start && $finish) :
$finishDate = DateTime::createFromFormat('Y-m-d H:i:s', $finish);
// 現在時刻が$finish前であれば表示
if ($currentDate < $finishDate) :
?>
<?php endif; ?>
こちらで設定が完了しました。
それぞれ条件分岐のなかに投稿を出力するコードをいれれば完成です。
実装が完了したら、試しに投稿開始・終了の予約がうまく処理されているかを確認してみましょう。
公開開始や終了がうまく動かない場合は、まず取得している日時が正確に取得できているかを確認しましょう$current ,$start, $finish のそれぞれを実際にechoしてみて意図している日時がきちんと出力できているかを確認しましょう。
ここでもし9時間のずれが発生している場合は、タイムゾーンが正しく設定できていない状態になっているので以下を確認してみましょう。
設定している日時が9時間ずれている場合
WordPressは標準ではUTC (協定世界時)が使用されており、日本時間はそこから+9時間された時刻になります。9時間のずれが発生している場合、タイムゾーンの設定が日本時間にできていない可能性が高いです。
管理画面からタイムゾーンを確認
WordPressの管理画面から「設定 > 一般」を開いて、タイムゾーンが東京になっているかを確認しましょう。
date_default_timezone_set()を使用している場合
テーマ内にdate_default_timezone_set()が使用されているとWordPressの設定時間がずれてしまいます。
基本的には使用しないことが推奨されています。WordPressで推奨されいているwp_date()などに変更できるのであれば、変更することをお勧めします。
まとめ
以上で、投稿の予約や終了時刻の設定に関しては以上です。
上記は通常の投稿一覧で設置していますが、カスタム投稿や、固定ページでの呼び出しなども可能です。
うまく設置できない場合は、タイムゾーンが正しく設定できているか、取得している値が正常に取れているか、条件分岐がただしくかけられているかなどを順番に確認しつつエラーの原因を探りましょう。
また、今回の方法はWordPress側で自動で非公開に切り替わるだけではなく、あくまでサイト側での表示がされないだけです。必要に応じて非公開や削除の設定は管理画面から行なってください。
最後にコード全体をもう一度掲載します。
基本的にはシンプルな条件分岐での処理になるので、仕様に応じてアレンジなどもしてみてくださいね。
完成したコード
<?php if( have_posts() ): ?>
<ul>
<?php while( have_posts() ) : the_post(); ?>
<?php
// 現在時刻
$current = wp_date('Y-m-d H:i:s');
$currentDate = DateTime::createFromFormat('Y-m-d H:i:s', $current);
// カスタムフィールドの値を取得
$start = get_field('start');
$finish = get_field('finish');
// $startと$finishの両方が設定されている場合
if ($start && $finish) :
$startDate = DateTime::createFromFormat('Y-m-d H:i:s', $start);
$finishDate = DateTime::createFromFormat('Y-m-d H:i:s', $finish);
// 現在時刻が$startと$finishの間にある場合
if ($startDate <= $currentDate && $currentDate < $finishDate) :
?>
<li><?php the_title(); ?></li>
<?php endif; ?>
<!-- $startのみ設定されている場合 -->
<?php elseif ($start && !$finish) :
$startDate = DateTime::createFromFormat('Y-m-d H:i:s', $start);
// 現在時刻が$start以降であれば表示
if ($startDate <= $currentDate) :
?>
<li><?php the_title(); ?></li>
<?php endif; ?>
<!-- $finishのみ設定されている場合 -->
<?php elseif (!$start && $finish) :
$finishDate = DateTime::createFromFormat('Y-m-d H:i:s', $finish);
// 現在時刻が$finish前であれば表示
if ($currentDate < $finishDate) :
?>
<li><?php the_title(); ?></li>
<?php endif; ?>
<!-- $startも$finishも設定されていない場合 -->
<?php else : ?>
<li><?php the_title(); ?></li>
<?php endif; ?>
<?php endwhile; ?>
</ul>
<?php endif; ?>
この記事の執筆者
