Slide 1

Slide 1 text

࣌Λࢧ഑͢ΔPHP #phperkaigi 2019.03.31 Hideki Kinjyo twitter: @o0h_ / github: o0h

Slide 2

Slide 2 text

౜ಥͰ͕͢

Slide 3

Slide 3 text

Έͳ͞Μ΋ࢥ͍·ͤΜ͔

Slide 4

Slide 4 text

͋ʙɺ͕࣌ؒͱ·Ε͹͍͍ͷʹɻ

Slide 5

Slide 5 text

Ͱ͢ΑͶʁ

Slide 6

Slide 6 text

ͦΕɺPHPͰͰ͖ΔΑʂ

Slide 7

Slide 7 text

ຊ೔ͷ͝঺հ

Slide 8

Slide 8 text

cakephp/chronos

Slide 9

Slide 9 text

ࣗݾ঺հ • ίωώτגࣜձࣾ • αʔόʔαΠυΤϯδχΞ • ओʹCakePHPͳͲ • ࠷ۙɺ{ॳ}ॻ੶Λࣥච͠·ͨ͠ ͸͡Ί·ͯ͠ʂ

Slide 10

Slide 10 text

TL;DR • cakephp/chronos
 A standalone DateTime library originally based off of Carbon • Date(calendar) / DateTimeͷศརͳॲཧΛఏڙ ͢Δ • ೔࣌ॲཧΛҕৡ͢Δ͜ͱͰɺ
 γεςϜ೔࣌ʹґଘ͠ͳ͍ʮݱࡏ೔࣌ʯΛॲཧ͕ Մೳʹ

Slide 11

Slide 11 text

Α͋͘Γͦ͏ͳ࿩

Slide 12

Slide 12 text

དྷ݄͸ɺզ͕ࣾ ͕ECαΠτʮଠ ࿠܅ͷ͓ห౰ശʯ Λ࢝Ίͯɺ7प೥ ͩɻ ײँͷؾ࣋ͪΛ ͜Ίͨɺεϖγϟ ϧηʔϧΛ΍Ζ ͏Α ࣾ௕ͷਓ

Slide 13

Slide 13 text

ࣾ௕͕ɺϫλ γʹͱͬͯ΋ ΤϞ͍࢓ࣄΛ ೚ͤͯ͘Εͨ ͧɻ͜Ε͸ઈ ରʹࣦഊͰ͖ ͳ͍ɺ͕Μ͹ Δ͔͠ͳ͍ʂ ৽ೖࣾһϫλγ

Slide 14

Slide 14 text

͋ʙΒΑͬʂͱɻ $template = 'itsumono_hanbai_page'; if (time() >= strtotime(START_SALE_DATETIME_STR)) { $template = 'special_taro_sale'; } render($template);

Slide 15

Slide 15 text

͜ΕͰɺ౰೔ ʹͳͬͨΒϖʔ δ͕੾ΓସΘ Δɻྑ͔ͬͨɺ ྑ͍ײ͡ʹ࢓ ࣄ͕Ͱ͖ͨͧɻ ৽ೖࣾһϫλγ

Slide 16

Slide 16 text

΍͊ɺ͕Μ͹ͬ ͨͶʂ΋͏Ұ ਓલ΋͍͔ۙ ͳʁ(স)͜Εͳ Β౰೔ɺΈΜ ͳେتͼʹҧ ͍ͳ͍ɻ๩͠ ͘ͳΔͧʙʙʂ པΕΔઌഐ

Slide 17

Slide 17 text

ͱ͜ΖͰ͞ʂ ͜Εͬͯɺ΋ ͏CI͸௨ͨ͠ ͔ͳʁͲ͏ͩͬ ͨʁ པΕΔઌഐ

Slide 18

Slide 18 text

͋ɺઌഐʂς ετͬͯ͜ͱ Ͱ͔͢ʁϩʔ ΧϧͰ͸ɺγ εςϜλΠϜ Λมߋͯ͠ಈ ࡞֬ೝ͸͠· ͨ͠ɻ ৽ೖࣾһϫλγ

Slide 19

Slide 19 text

Ͱ΋ɺΉΉΉɺ ͔֬ʹςετ ίʔυ͸ɾɾɾ runkitͱ͔ೖ ΕͪΌ͍ͬͯ ͍Ͱ͔͢Ͷʁ ৽ೖࣾһϫλγ

Slide 20

Slide 20 text

͏Μ͏Μɺͦ ͏ͩΑͶɻͦ Μͳ࣌ʹɺͱͬ ͯ΋ศརͳ΋ Μͷ͕͋ΔΜ ͩɻ པΕΔઌഐ

Slide 21

Slide 21 text

cakephp/chronos͞ʂ

Slide 22

Slide 22 text

৭ʑͱػೳ͕ ͋ΔΑ པΕΔઌഐ

Slide 23

Slide 23 text

໨Լͷ๻Βͷ ؔ৺ͱͯ͠͸ɺ ʮtesting aidʯػೳ͕໾ ʹཱͪͦ͏ͩ ͔Βɺ঺հ͢ ΔͶɻ པΕΔઌഐ

Slide 24

Slide 24 text

setTestNow()

Slide 25

Slide 25 text

before $template = 'itsumono_hanbai_page'; if (time() >= strtotime(START_SALE_DATETIME_STR)) { $template = 'special_taro_sale'; } render($template);

Slide 26

Slide 26 text

·ͣ͸ɺʮݱࡏʯʹ͍ͭͯ
 ͢΂ͯChronosܦ༝ͰऔΓग़͢Α͏ʹॻ͖׵͑ΔΑ use Cake\Chronos\Chronos; $template = 'itsumono_hanbai_page'; if (Chronos::now() >= strtotime(START_SALE_DATETIME_STR)) { $template = 'special_taro_sale'; } render($template);

Slide 27

Slide 27 text

͍ͭͰʹɺ
 ૬खํ΋ॻ͖׵͑ͯ͠·͓͏ use Cake\Chronos\Chronos; $template = 'itsumono_hanbai_page'; if (Chronos::now() >= new Chronos(START_SALE_DATETIME_STR) ) { $template = 'special_taro_sale'; } render($template);

Slide 28

Slide 28 text

ൺֱϝιουΛ࢖͏ͱ
 ܕνΣοΫ΋Ͱ͖ΔͷͰɺ͓޷ΈͰɻ use Cake\Chronos\Chronos; $template = 'itsumono_hanbai_page'; if (Chronos::now()->gte(new Chronos(START_SALE_DATETIME_STR)) ) { $template = 'special_taro_sale'; } render($template);

Slide 29

Slide 29 text

ϓϩμΫτίʔ υͷ४උ͸Ͱ ͖ͨɻͯ͞ɺ ͜ΕͰςετ ͕ॻ͚ΔΜͩ Αʂ པΕΔઌഐ

Slide 30

Slide 30 text

testίʔυΛॻ͍ͯΈΔ /** * @test */ public function セール開始前() { Chronos::setTestNow('2019-03-10'); $targetPageUrl = '/'; $actual = get($targetPageUrl); $this->assertTitleIs( '太郎君のお弁当箱', $actual ); }

Slide 31

Slide 31 text

testίʔυΛॻ͍ͯΈΔ /** * @test */ public function セール開始前() { Chronos::setTestNow('2019-03-10'); $targetPageUrl = '/'; $actual = get($targetPageUrl); $this->assertTitleIs( '太郎君のお弁当箱', $actual ); } ͜͜ʹೖΕͨ஋͕
 A$ISPOPTOPX AʹͳΔ

Slide 32

Slide 32 text

testίʔυΛॻ͍ͯΈΔ /** * @test */ public function セール期間中() { Chronos::setTestNow('2019-04-01'); $targetPageUrl = '/'; $actual = get($targetPageUrl); $this->assertTitleIs( '太郎君のお弁当箱〜7周年ありがとう!〜', $actual ); } ֘౰ظؒʹ͓͍ͯ͸
 ϖʔδ಺ίϯςϯπ͕
 ࠩ͠ସΘΔ͜ͱΛظ଴͢Δ

Slide 33

Slide 33 text

testίʔυΛॻ͍ͯΈΔ /** * @test */ public function セール終了後() { Chronos::setTestNow('2019-05-01 06:59:59’); $targetPageUrl = '/'; $actual = get($targetPageUrl); $this->assertTitleIs( ‘太郎君のお弁当箱', $actual ); } ࣌ࠁϨϕϧ·ͰݻఆՄೳ

Slide 34

Slide 34 text

͓ͬͱɺऴྃ೔ ࣌ͷઃఆΛͯ͠ ͳ͔͔ͬͨ΋Ͷʂ ΋ͪΖΜɺ͙͢ ʹ͸ඞཁͳ͍͚ Ͳɺࠓͷ͏ͪʹ ΍͓͍ͬͯͪΌ ͑͹҆৺ͩͶʂ པΕΔઌഐ

Slide 35

Slide 35 text

Θɺ͋Ϳͳ͍ʂ ઌഐ͋Γ͕ͱ ͏͍͟͝·͢ʂ ΍ͬͺΓɺς ετ͕(͔͠΋ ؆୯ʹ)ॻ͚Δ ͱ҆৺ײ͕͋ Δͳʙ ৽ೖࣾһϫλγ

Slide 36

Slide 36 text

ͪͳΈʹɺ `setTestNow(null )` ͯ͋͛͠Ε͹ɺ ϑΣΠΫ೔࣌Ͱ͸ ͳ͘ݱ࣮ͷ೔͕࣌ ฦͬͯ͘ΔͷͰ҆ ৺͞ɻςετͰ࢖ ͏࣌ͱ͔͸ɺ tearDown()ʹڬΜ Ͱ͓͖͍ͨͶɻ པΕΔઌഐ

Slide 37

Slide 37 text

ଞʹ΋ศརͳ͜ͱ (࣌ؒ͋Ε͹Ͷ!)

Slide 38

Slide 38 text

৭ʑͱϔϧύʔͳͲ • DateTimeInterface΍DateTimeImmutableͷػೳ͸ͦͷ··࢖͑Δͷ ͰɺҠߦ΋ͦΜͳʹ͠ΜͲ͘ͳ͍͸ͣ • add/sub/diffͳͲͳͲ • ೔࣌ૢ࡞ʹɺʮࣗવจͬΆ͍දݱͰಡΈ΍͍͢ʯAPI͕૿͑Δҹ৅ • ge/gte/lt/lte/between/wasWithinLastͳͲͷൺֱػೳ • addDays(int $value) / subMonths(int $value)ͳͲͷߋ৽ػೳ • Chronos::yesterday() / Chronos::instance(DatetimeInterface $dt) ͳͲͷϑΝΫτϦ

Slide 39

Slide 39 text

ΞάϨογϒͳ࢖͍ํ isSunday()) { goto doNidone(); }

Slide 40

Slide 40 text

(ͪͳΈʹ)cakephpͷ৔߹ • I18nܥύοέʔδͰܧঝͨ͠ɺTime/FrozenTime ͕ར༻͞Ε͍ͯΔ • timezone΍localeͷ৘ใΛ͍࣋ͬͯΔ • https://github.com/cakephp/i18n/blob/master/ FrozenTime.php • ORMܦ༝ͰRDBMS͔ΒऔΓग़ͨ͠datetimeྻͷ ஋͸ɺࣗಈతʹίΠπʹϚʔγϟϧ͞ΕΔ

Slide 41

Slide 41 text

·ͱΊ

Slide 42

Slide 42 text

·ͱΊ(1/2) • ςετ = ҆৺ײ • ςελϒϧ = ઃܭͷ࿩ɺςεςΟϯάϑϨʔ ϜϫʔΫ(etc)ଆͷදݱྗͷ࿩ • ࣌Λࢧ഑͢Δͱͱͬͯ΋ศར
 ಛʹςετɺ͜ΕͰTDD΋΍Γ΍͍ͧ͢ʂ

Slide 43

Slide 43 text

·ͱΊ(2/2) • cakephpνʔϜͷϝϯς͚ͩͲɺελϯυΞ ϩϯͰ࢖͑ΔͷͰɺͲ͜ʹͰ΋࿈Ε͍͚ͯΔʂ • ʮਂ໷0࣌ʙਂ໷2࣌ͷؒ͸௨Βͳ͍ʯ͔Βͷ ଔۀɾɾɾʂ

Slide 44

Slide 44 text

͓෇͖߹͍͍ ͖ͨͩ
 ͋Γ͕ͱ͏͝ ͍͟·ͨ͠ʂ