PHP
twig
CeresDay 4

現在過去未来 行き放題にするおまじない

日付指定で公開されるコンテンツを簡単にデバッグする

WEBサイトを作っていると、このキャンペーンは、○日から告知したい、また、このページは○日で終わりにしたい。などの時間帯表示制御を入れたくなるのが人の性。ただ、モノによっては、夜中0時からスタートするという、システム屋泣かせな企画もあるかと思います。そんな時、テストって皆さんどうしてますか?

  • OSのシステムの時刻をずらして切り替わるかテストする
  • 切り替えの時間を現在時刻+2分くらいにして、切り替わることを担保する
  • PHPTimecop等(hnwさん作)を使う

いろいろあるかと思います。

非システムメンバーが簡単に確認する方法は?

前述の対応を使うと、システムにあまり詳しくないメンバーは確認するために都度エンジニアに依頼をすることとなります。って、これ毎回やるの?お互い大変!

もっと簡単にできる方法を考えてみた

準備するもの

  • 適当なPHP MVCフレームワーク・・・・・・・・・1式
  • TWIG等のテンプレートエンジン ・・・・・・・・1式

設計方針

非システムメンバーに、【直感的に確認してもらえる方法】はなんだろう?と考えた時、今表示されているURLの後ろにGETパラメータで日時指定できたら楽かも・・・と思いつく。

要件の確認

  • 年月日を指定することで、対象ページのその日の状態を見ることができる
  • 時間で切り替わるコンテンツもあるので、時分秒でも指定できる
  • テンプレートで指定時刻を使った表示制御ができる

実装方法の検討

ページによって、引数を受け付ける内容が違うので、フレームワークの場合ルーティング部分(コントローラー部分)に引数の制御及び、バリデーションロジックを一つひとつ細かく書いてくのが面倒。(フレームワークによっては、ミドルウェア部分でできるけど)ってことで、大抵どのページも通る公開ディレクトリのindex.phpにロジックを書く。

※ここでは、?static_date=YmdHisを共通の引数として、サイト内では$static_dateを現在時刻として扱う様にする。

実装

index.php
//static_dateがあればその内容を$appの配列に追加する
if(isset($_GET['static_date']) && $_GET['static_date'] && is_numeric($_GET['static_date'])){
    //その内容をタイムスタンプとして$appの配列に追加する
    $app['static_date'] = strtotime($_GET['static_date']);
} else {
    //なければ、現在時刻を指定
    $app['static_date'] = time();
}

テンプレート実装方法の検討

View側で変数の設定値を見て日付を比較、日付が表示する範囲内の場合は表示、範囲外の場合は非表示とするロジックを実装。

実装

※例はTWIGを利用したもの。

view
{% if app.static_date | date("Ymd") == "20181219"  %} 
12月19日おめでとう!
{% endif %}

TWIGでは、日付をdate()でフォーマットできるのでその部分を利用する。

フォーマット 内容
Y 年を西暦で取得 2018
m 月を0埋めで取得 08
d 日を0埋めで取得 05
H 時間を取得(24時間) 23
i 分を0埋めで取得 05
s 秒を0埋めで取得 09
日時取得SAMPLE
{# 現在の年月日を取得 20181204#}
{{ "now" | date("Ymd")  }} 
{# 現在時分秒を取得 152532#}
{{ "now" | date("His")  }} 

使い方

時間で出し分けするコンテンツを見たいページのURLの末尾に、
?static_date=20181219
をつけて12月19日をシミュレートする。

アクセスURL
https://example.com/?static_date=20181219

でアクセスすると、

サイト表示
12月19日おめでとう!

と画面に表示され、表示されない日の12月14日をシミュレートすると

アクセスURL
https://example.com/?static_date=20181214

なにもでない様になる。
同様に、時間帯制御も可能。例えば、12月19日12:00~13:00だけ出したいものは

12月19日12:00~13:30だけ
{% if app.static_date | date("YmdH") >= "2018121912" and app.static_date | date("YmdHi") <= "201812191330" %} 
昼だね。今日12月19日は、何食べ行こうか?
{% endif %}

という要領で使える。

注意

このまま、サービスをしてしまうと、サイト閲覧者が、先々のキャンペーン予定を知っちゃったりして、諸々危険なので、この動作は開発環境でのみ実行するようにしておいたほうが良いと思います。Apacheを使っている場合、httpd.confに環境を識別する変数env等を指定し、それをアプリ側で判別、機能のOn/Offを切り替えるようにしときましょう。

環境を見て挙動を変更する
//開発環境で且つstatic_dateが引数にあれば
if(isset($_GET['static_date']) && $_GET['static_date'] && is_numeric($_GET['static_date']) && $_SERVER['env']=="dev"){
    //その内容をタイムスタンプとして$appの配列に追加する
    $app['static_date'] = strtotime($_GET['static_date']);
} else {
    //なければ、現在時刻のタイムスタンプを指定
    $app['static_date'] = time();
}

まとめ

やり方はいろいろあると思いますが、非システムメンバが確認しやすい環境を作ってあげるのもエンジニアとして必要なタスクかと思います。それと、たまに、過去の日付を指定して、昔のキャンペーン等を見てノスタルジーに浸ってみるのも良いかもしれませんね。