composer require cakephp/chronos:^1.2
setTestNow()
メソッドがクラスを横断して時刻セットできるようなった!
CakePHP 3.2以降、時刻操作クラスとして cakephp/chronos が採用されています。
CakePHP内ではChronosを継承した \Cake\I18n\FrozenTime
, \Cake\I18n\Time
, \Cake\I18n\FrozenDate
, \Cake\I18n\Date
を使用でき、データベースの時刻系のフィールドはこれらのクラスへマッピングされます。
また、Chronosにはテストを容易にするためにsetTestNow()
というメソッドがあり、各クラスの現在時刻を指定の時間へ固定することができます。
use \Cake\I18n\FrozenTime;
FrozenTime::setTestNow('1975-08-08 11:22:33');
$time = new FrozenTime('1 hour ago'); // 1975-08-08 12:22:33
$now = FrozenTime::now();
FrozenTime::setTestNow($now);
sleep(10); // 10秒待つ
$currentTime = FrozenTime::now(); // 固定されているので $currentTime == $now
Chronos 1.1 までの問題
しかし、Chronos 1.1 までは、setTestNow()
は各クラスごとにセットしなければなりませんでした。
以下のようにFrozenTime::setTestNow
はTime
クラスへ影響しません。
use \Cake\I18n\FrozenTime;
use \Cake\I18n\Time;
FrozenTime::setTestNow('1975-08-08 11:22:33');
$time = new FrozenTime('1 hour ago'); // 1975-08-08 12:22:33
$time = new Time('1 hour ago'); // 現在時刻の1時間後
CakePHP 3.2以降のデフォルトでは、時刻系のフィールドは FrozenTime
で処理されるようになっています。
通常は FrozenTime::setTestNow
で時刻セットを行えばよいのですが、1ヶ所だけ Time
が使われる部分があります。
TimestampBehavior
の内部では、Time
が使用されています。ですので、テスト時に FrozenTime
のみ時刻を固定した状態で created
などの TimestampBehavior
によりセットされる時刻フィールドをみると、固定した時刻ではなく実行時の時刻が入っていることになります。
これに対処するには、FrozenTime
, Time
の双方にテスト時刻をセットすればよいのですが、冗長な記述となっていました。
Chronos 1.2 ではこの問題が改善された
Chronos 1.2以降、setTestNow
での設定はすべてのChronosのサブクラスへ伝播するようになりました。
use \Cake\I18n\FrozenTime;
use \Cake\I18n\Time;
FrozenTime::setTestNow('1975-08-08 11:22:33');
$time = new FrozenTime('1 hour ago'); // 1975-08-08 12:22:33
$time = new Time('1 hour ago'); // 1975-08-08 12:22:33
これにより、各時刻クラスへのsetTestNow
の漏れがなくなり重複した記述を減らせるので、今すぐChronos 1.2以降へバージョンアップすることをお勧めします。
FEBLrz0zSqq
C51KRcwQscb
TspmtOLF9vo
kvK98hBy65G
h6g5aLI57UZ
dn6ffxGZFmM
x2vMr77AOxr
lD5gdUhZ74S
K38JHo2QL5j
1pg14GQSpKw
2I2NTx1xuaX
QWe5RI3z6uk
lkOj6dS7AYS
zqeguy1P2q6
T4lU6EfB0a2
IHlJhtpwatQ
iZsPzIL3F5B
vKeTAvc3GCw
OG95BGEvtn5
AFLZU7upXQ3
owcvbt644nt
hw7E9dkF7BP
R6jeXaInHHB
cNtgSlZrpxN
iUz5CMpqVSQ
MEWcu2cSO2D
0CROVGP0ZF2
h1x7Ol2F1Y4
lkVwJALyWl6
Ddd1pIy8s2Q
IEx5E8NMa0O
TKxGKmxvKjU
q2nV2BOYjKH
IjAPZgtCZlc
d6w2jOdIY4b
aQiwo7Exate