Slide 1

Slide 1 text

ؼ͖ͬͯͨʂ ฏ੒࠷ޙͷ ΦϨΦϨϑϨʔϜϫʔΫͷ ࡞Γํ » PHPerKaigi 2019 » 2019/03/22 » @uzulla

Slide 2

Slide 2 text

ʮؼ͖ͬͯͨʯʁ » ʮPHPerਓੜɺҰ౓͸ϑϨʔϜϫʔΫΛ࡞͓ͬͯ͜ ͏ʂʯ » PHPΧϯϑΝϨϯε๺ւಓ 2016 » https://speakerdeck.com/uzulla/phperren- sheng-du-hahuremuwakuwozuo-tuteokou » ࣍ͷϖʔδ͔ΒμΠδΣετ

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

No content

Slide 8

Slide 8 text

No content

Slide 9

Slide 9 text

ࠓ೔ͷ΋ͷΑΓॳ৺ऀ޲͚ͳ ͷͰɺͥͻɻ » ࿩Λ໭͠·͢ɻ

Slide 10

Slide 10 text

#ΦϨΦϨϑϨʔ ϜϫʔΫ ͱ͸ʁ » (ϑϨʔϜϫʔΫ(ҎޙFW)ͷઆ໌ ͸͠·ͤΜ) » ࣗ෼Ͱ࡞ͬͨFW -> ΦϨΦϨFW » ݱ୅Ͱ͸ϑϨʔϜϫʔΫ͸ ʮબͿʯ΋ͷ » ੲ͸ϑϨʔϜϫʔΫ͸ͳ͔ͬͨ » ΈΜͳϑϨʔϜϫʔΫΛͭͬ͘ ͨ΋Μ͡Ό…ʢॾઆ͋Γ·͢ʣ

Slide 11

Slide 11 text

» جຊతʹɺݱ୅Ͱ͸ɺΦϨΦϨ͸ආ͚Δ΂͖ߦҝͱ ͞ΕΔ » ࣗզͷڧ͍FW͸Έͳ͕޾ͤʹͳΕͳ͍͜ͱ͕ଟ ͍

Slide 12

Slide 12 text

ͦ΋ͦ΋ɺFWͷར఺͕େମͳ͘ͳΔ » ੜ࢈ੑɺ඼࣭ͷ޲্ » ݱ࣮Ͱςετ͞ΕͨϥΠϒϥϦ » ϕλʔϓϥΫςΟεͳख๏ » େن໛։ൃͷجૅ » υΩϡϝϯτͷ੔උ » ΤϯδχΞͷֶश » ΤίγεςϜ » ར༻ऀͷϒϩά΍࣭໰αΠτͰͷճ౴ » ϓϥάΠϯͷ๛෋͞

Slide 13

Slide 13 text

ΦϨΦϨϑϨʔϜϫʔΫͷར఺ʢʁʣ » ͦͷਓ͕͕Μ͹Ε͹ϝϯς͕ଓ͘ » ʢεΩϧͷ͋Δਓ͕ͦΜͳۀ຿ʹ͔·͚͍ͯΔΘ͚ʹ ΋…ʣ » ʮͦͷ࣌ͷʯ(ఆܗ)ۀ຿ʹదͨ͠ઃܭʹͳΔ » ʢ࣌୅͸มΘΓ·͢ͷͰ…Ψϥέʔ޲͚ػೳ͕ࠓ͋ͬͯ ΋…ʣ » OSSʹཔΒͳ͍ͰࡁΉ » ʢʮϥΠηϯεͬͯΑ͘Θ͔Βͳ͍ΜͩΑͶʯʮͳΔ΄ Ͳʯʣ

Slide 14

Slide 14 text

ͳͷʹɺͳͥࣗ࡞ͯ͠͠·͏ͷ͔ʁʁ » ΦϨΦϨϑϨʔϜϫʔΫΛʮ࡞Δʯͱຊਓͷܦݧ஋͸૿͑ Δ » ʢධՁ͞ΕΔ͔͸ผʣ » ൚༻తͳྗͷ޲্ » ຊਓͷ૝૾ྗɾίʔυϦʔσΟϯάͷεΩϧΞοϓ » ίϐʔ͢Δͷ΋؆୯Ͱ͸ͳ͍ » ͳʹ͔͏·͍͔͘ͳ͍࣌ɺFWͷίʔυΛಡΊΔ » ʮͳ͔ͥ͜ΕͰ͏͘͝ʯ͕ݮΔ

Slide 15

Slide 15 text

ʮͪΐͬͱ·ͬͯʂʯ » ͋ͳͨͷʮࠓͷ࢓ࣄʯ͸ΦϨΦϨϑϨʔϜϫʔΫΛ࡞Δ ͜ͱ͔ʁ » ੈքฏ࿨ʹ͸ڵຯ͕ͳ͍ͷ͔ʁ » ࣗ୐ͰӅΕͯͬͦ͜Γ΍Γ·͠ΐ͏ » Ұ౓΋࡞ͬͨ͜ͱແ͍ͷ͸Ͳ͏ͳͷ͔ʁʢ࿝֐ൃݴʣ » ؾ߹Λ͍Ε͍͚ͯ͹ɺΦϨΦϨ͔Β௒͍͑ͯ͘͜ͱ ΋…ʂ » ʮͦͷ֮ޛ͸͋Δ͔ʁʯʮͳ͍Θʔʔʯ

Slide 16

Slide 16 text

» https://twitter.com/excite__pr/status/ 1082482594401288193

Slide 17

Slide 17 text

΍͍͖ͬͯ·͠ΐ͏

Slide 18

Slide 18 text

ॳ৺ऀ޲͚ɺΦϨΦϨ࡞੒ʹ͋ͨͬͯඞཁͳ৺ߏ ͑ » ंྠ FWͷ࠶ൃ໌ʹ͋ͨͬͯͷ৺ߏ͑Λ఻͑·͢

Slide 19

Slide 19 text

ंྠ͸࠶ൃ໌͢Δ΋ͷ » ਓؾͷंྠ͸།Ұ࠷ߴͷंྠͰ͸ͳ͍ » ͋ͳͨͷυϝΠϯʹϚον͍ͯ͠ͳ͍͔΋ » ࠷ߴ͸৭ʑ༗Δ » ྫɿάϦοϓྗ͕௿ͯ͘΋ɺύϯΫ͠ͳ͍λΠϠ͕͍͍ » ྫɿτϥϯΫʹੵΉۓٸ༻͔ͩΒখ͍͞ͷ͕ྑ͍ » ଞਓ͕࠷ߴͱײ͡Δඞཁ͸ͳ͍ » ʮ˓˓ͷFWͷ͜Ε͸࠷ߴʂʯ͸ΦϨΦϨͱ૬൓͠ͳ͍ » श࡞ͳΒʮࣗ෼ͷʯ࠷ߴΛ໨ࢦ͢ͱΑ͍

Slide 20

Slide 20 text

ंྠ͸ंྠͩ » Ͱ͖Ε͹ૉ௚ʹؙ͘࡞Ζ͏ » ߴػೳͰͳͯ͘΋ɺؙ͚Ε͹ंྠʹ͸ͳΔ » ͨͱ͑͹ɺΑ͋͘ΔϧʔλʔΛ࡞Δ(͚ͭΔ) » ʮͳΜͰଞͷϑϨʔϜϫʔΫ͸͜͏ͳͬͯͳ͍Μͩʁ ԶͳΒ͜͏͢Δʂʯ

Slide 21

Slide 21 text

» ʮಉ྅ʹ࠘·Εͳ͍ΦϨΦϨ΋͋Δ͸ͣͳΜͩɺͦ ͏ݴͬͯஉ͸εύήοςΟͷ৿ʹফ͑ͨ…ʯ » ͩΕ΋΍͍ͬͯͳ͍ઃܭ͸᠘͔΋ɺ஫ҙʂ

Slide 22

Slide 22 text

Α͋͘ΔਥೋපɺREST(ful)ฤ » (APIʹ͓͍ͯ͸)REST෩ͳύεύϥϝʔλʹ΋ٙ໰͕͋Δ » /book/1ͱ͔΍Δͱɺཪଆʹbookςʔϒϧͷid1͕ඞਢͱ͔ ͋Γ͕ͪ » ϦιʔεʢDBͷςʔϒϧͱີ݁߹ʣࢤ޲͸ݶք͕͋ΔͷͰ ͸ » ʮ_methodͬͯͳΜͩΑϫϩλɺେࣗવʹPATCHͳ͍΍Ζʯ » ʮഁյ͕ͳ͍ͳΒGETʯͷ༥௨ͷ͖͔ͳ͞ » ߴ౓Ͱগͳ͍ίʔυΑΓɺόΧͰ΋Θ͔Δྔͷ͋Δίʔυ ͷ΄͏͕ͳΜͱ͔ͳΓ΍͍͢ʢओ؍ʣ

Slide 23

Slide 23 text

ઌߦ੡඼Λ͔͍ͭ͜ͳͤ » ͔͍ͭ͜ͳͤͳ͍͍͍Θ͚ͰΦϨΦϨΛͭͬͯ͘͸ͳ Β͵ » (͢ΔͱʮΦϨΦϨ͍Βͳ͍ͳʁʯͱ͍͏ฏ࿨ͳॴʹ ߦ͖ண͘ࣄ΋͋Γ·͢ɻ)

Slide 24

Slide 24 text

ंྠ͸෦඼ͩ(ओ؍) » ʮಛ஫඼ʯ͸ආ͚Δ΂͖ » ઃܭͷ࣮ફςετෆ଍ » ࠷ߴͷ෦඼͸൚༻෦඼ͩ » ୅ସ͕ޮ͘

Slide 25

Slide 25 text

» ͨͱ͑͹ϧʔλʔ » ΄ͱΜͲͷ΋ͷ͸IFઃܭ͕ࣅ͍ͯΔ » ʢݱ࣮ੈքͰ࣮ূ͞Εͨ࢖͍΍͢͞ʣ » ަ׵Ͱ͖Δ » ʢAPI͸ۃ୺ʹ͸มΘΒͳ͍ͷͰɺ࡞ͬͯࠩ͠ସ ͑΍͍͢ʣ » ࢖͍ํ΋ʹͨΓΑͬͨΓ » ʢֶशίετ͕௿͍ʣ

Slide 26

Slide 26 text

৺ߏ͑·ͱΊ » ʮੈؒͷ࠷ߴʯ͸Αͦʹஔ͘ » श࡞͔ͩΒͦ͜ » ʮ͋Ε͕ͳ͍ɺ͜Ε͕ͳ͍ʯ͸ແ༻ » Ͳͷ෦෼ͷந৅౓Λ্͛Δ͔͸ɺҊ݅ʹΑΔ » ͱ͸͍͑ɺయܕྫΛ໛฿͢Δͱഁ୼͠ਏ͍ » (ΦϨΦϨͰഁ୼Λؾʹ͢Δͷ͔ʁ)

Slide 27

Slide 27 text

ॳ৺ऀ޲͚ͷखͷ෇͚ํ » ॳ৺ऀ͸طଘͷϑϨʔϜϫʔΫͰΞϓϦΛ࡞ͬͯΈΔ ͱΑ͍ » ඞཁͳॴ͕ݟ͑ͯ͘Δ » ؾʹ৯Θͳ͍෦෼΋ݟ͑ͯ͘Δʢ͕ࣗ͜͜ݾຬ଍ ͷͨΊʹॏཁʣ » ʢ΋͠ຬ଍Ͱ͖Ε͹ؙṶ͚ʣ » ͦΕΛΦϨΦϨFWʹҠ২͠Α͏ʂ

Slide 28

Slide 28 text

ॱ൪ʹͭͬͯ͘ɺࠩ͠ସ͍͑ͯ͘ » શ෦ΛҰؾʹͭ͘Βͳ͍ͱಈ͔ͳ͍ͱͭΒ͍ » ͪΐͬͱͮͭஔ͖׵͍͑ͯ͘ » (͢ΔͱɺϑϧελοΫͰͳ͘ɺ෦඼୯ҐͷFW͕ Α͍Ͷʁ) » Ͱ΋ɺπΪϋΪͬΆ͘ͳΔΑͶ…ʁ » ϑϧελοΫ͸ࣗ৴͕Ͱ͖͔ͯΒ΍Ζ͏

Slide 29

Slide 29 text

ॳ৺ऀ͕(؆୯͔ͩΒ)࡞Δ΂͖ػೳ » ϧʔλʔ » όϦσʔλʔ » DI෩ίϯςφ » ςϯϓϨʔτΤϯδϯ…ͷϔϧύʔ

Slide 30

Slide 30 text

Ϥγʂ » ʮLaravelΈ͍ͨͳςϯϓϨʔτΤϯδϯ࡞Ζ͏ʯ » ʮLaravelΈ͍ͨͳDIΛ࡞Ζ͏ʯ » ʮLaravelΈ͍ͨͳORMΛ࡞Ζ͏ʯ » ʮΑ͠ʂ-BSBWFMͷίʔυಡ΋͏ʂʯ

Slide 31

Slide 31 text

…ʢॳ৺ऀʹ͸ʣແཧͰ͸ʁʁ » ࢖͏ػೳ͕ࣗ෼Ͱͭ͘Εͳ͍ʁ » ΦϨΦϨ͔ͩΒఘΊΔʁ » SUGOIϥΠϒϥϦΛ࢖͏ʁ » ࢓༷ଆΛม͑Δʁ » खஈ͸ͳΜͰ΋ΞϦͩΑɺͩͬͯΦϨΦϨͩ΋Μ » (ྫྷ੩ʹͳͬͯ͜͜ͰΦϨΦϨ࡞੒ΛࢭΊΔ((?ʁ

Slide 32

Slide 32 text

ॳ৺ऀ͕ݟΔ΂͖ϑϨʔϜϫʔΫ » ݹ͍Μ͚ͩͲɺFWͷίʔυΛಡΜͩ͜ͱ͕ͳ͍ͳΒ·ͣ͸͜ͷลΓΛ ಡΉͱྑ͛͞ » ੿࡞ͷOre1,2 » https://github.com/uzulla/Ore » https://github.com/uzulla/Ore2 » Limonade » Slim Frameworkͷ2.xܥ » phpixieͷ2.xܥ » ͜ΕΒ͸ൺֱతಡΈ΍͍͚ͩ͢Ͱ (Ұൠతʹ͸)࠷ߴͷ'8Ͱ͸ͳ͍ɺ೦಄ʹ͓͘͜ͱ

Slide 33

Slide 33 text

ଞɺαϯϓϧίʔυͷ୳͠ํ » GitHubΛͱΓ͋͑ͣݕࡧͯ͠ΈΔ » php web frameworkͱ͔Ͱݕࡧ » GHʹ͸੕ͷΑ͏ʹɺຖ೔ΦϨΦϨFW͕ര஀ͯ͠ ͍ΔͷͰ༐ؾ͕༙͘ʂ » Ͱ͖Ε͹Star͕ଟͯ͘ɺίʔυ͕ಡΊͦ͏ͳ΋ͷ͕ Α͍ » ͱΓ͋͑ͣ৭ʑಈ͔ͯ͠ΈΔ

Slide 34

Slide 34 text

Tips » Commit͕গͳ͍΋ͷ͸஍ཕʢͱ͍͏͔׬੒ͯ͠ͳ͍ʣ » υΩϡϝϯτ͕΋ͷ͘͢͝੔උ͞Ε͍ͯΔ΋ͷ͸༻్͕൚༻త͢ ͗Δ͔΋ʢ༷ʑͳέʔεʹରԠ͢ΔͨΊɺෳࡶͩͬͨΓ͢Δʣ » ίϛολʔ͕͘͢͝ଟ͍΋ͷ͸ඍົ » ϓϥάΠϯ͕ͳ͍΋ͷ͕Α͍ʢϓϥάΠϯΛ࣮ݱ͢ΔͨΊʹɺෳ ࡶͳ͜ͱ͕ଟ͍ʣ » ʮ͋Εʹ΋͜Εʹ΋ରԠʂʯ͸ʢίʔυ͕୹͘ͱ΋ʂʣந৅౓ ͕ߴ͘ɺֶͼ͸͋Δ͕ෳࡶ » ૉ௚ʹʮ͜Ε͔͠Ͱ͖·ͤΜʂʯͷ΄͏͕౰વ୯७

Slide 35

Slide 35 text

ͦͯ͠࡞ऀʹܟҙΛ » ଟ͘ͷOSSϥΠηϯε͸ྲྀ༻͕Ͱ͖Δɺ࠷ߴʂ » ͨͩ͠ϥΠηϯεʹ͸ै͏͜ͱ » MITͳΒAuthor౳ΛͲ͔͜ʹࡌͤΔͳͲ » GPL͔Βྲྀ༻͢ΔͳΒɺGPLʹ͢ΔͳͲ » ϥΠηϯεهࡌͷͳ͍ϒϩά౳͔Βͷసࡌ͸NG

Slide 36

Slide 36 text

» ΦϨΦϨͱ͸͍͑FWΛ࡞Δͷ͔ͩΒɺϥΠηϯεʹ ͍ͭͯ͸ֶ΅͏ » ·͋ઈରʹ഑෍͠ͳ͍ͳΒ͍͍͚Ͳɺޙ͔Β୳͢ͷ͸ େม » (ͦͷ΄͏͕ฏ࿨Ͱ͸ʁʁ) » ͱΓ͋͑ͣɺྲྀ༻ͨ͠ίʔυͷҾ༻ݩURL͘Β͍ϝ Ϟ͓ͬͯ͜͏

Slide 37

Slide 37 text

Ͱ͸ॳ৺ऀ͕FW੡࡞࣌ʹॻ͘΂͖ΞϓϦͱ͸ʁ » ͱ͸ʁ » Ұ௨Γͷػೳ͕ඞཁͰ » ͱΔ΂͖ڍಈ͕͸͖ͬΓ͍ͯ͠Δ΋ͷ » (୯७͔ɺ͓खຊ͕͋Δ΋ͷ)

Slide 38

Slide 38 text

ೖ໳ » URL͕index.phpͰ͓ΘΒͳ͍΋ͷ » GET,POST͕͋Δ΋ͷ » Ϣʔβʔ͕ࣗ༝ͳจࣈΛೖྗͰ͖Δ΋ͷ » ʢϑΥʔϜͷʣ֬ೝը໘͕͋Δ΋ͷ » ʢϑΥʔϜͷʣϑΟʔϧυʹ੍໿ʢͨͱ͑͹ϝΞυʣ ͕͋Δ΋ͷ » = ϝʔϧϑΥʔϜʁ

Slide 39

Slide 39 text

ॳڃ » CSRF TokenΛඋ͑Δ΋ͷ » HTMLҎ֎ɺJSON౳ΛϨεϙϯεͰ͖Δ΋ͷ » ϦμΠϨΫτ͕͋Δ΋ͷ » σʔλϕʔεʹಡΈॻ͖ߋ৽͢Δ࢓૊Έ » = ܝࣔ൘ʁ

Slide 40

Slide 40 text

தڃ » ϩάΠϯʢSessionʣ͕͋Δ΋ͷ » αΠϯΞοϓ͕͋Δ΋ͷ » Delete FlagͰͷ࡟আ » (Del flag͕ྑ͍ͱݴ͏͜ͱͰ͸ͳ͍ʣ » ೚ҙͷΧϥϜͰͷ߱ॱɾঢॱιʔτ » N+1తͳɺෳ਺ͷςʔϒϧΛ݁߹͢Δඞཁ͕͋Δ΋ͷ » Ϣʔβʔը໘ͱ෼཭͞Εͨ؅ཧը໘͕͋Δ΋ͷ » = ձһ੍ܝࣔ൘ʁ

Slide 41

Slide 41 text

্ڃ » ϑΝΠϧΛΞοϓϩʔυ͢Δ΋ͷ » ʢڊେͳɺϝϞϦ͔ΒᷓΕͦ͏ͳʣϑΝΠϧΛμ΢ϯϩʔ υ͢Δ΋ͷ » ෳ਺ΧϥϜͷΩʔϫʔυݕࡧ » ೚ҙͷෳ਺৚݅Ͱͷݕࡧ » ૯݅਺͕දࣔ͞Ε͍ͯΔϖʔδϟʔ » ACL » = (΢ΣϒUIͷ)*OTUBHSBN

Slide 42

Slide 42 text

௒্ڃ » SNSΈ͍ͨͳҟৗʹେྔͷRoute΍Model͕͋ΔαΠ τ » ECαΠτΈ͍ͨʹେྔͷϩοΫɾτϥϯβΫγϣ ϯɾ֎෦࿈ܞ͕ඞཁͳαΠτ » ιγϟήΈ͍ͨʹେྔͷΞΫηε͕ͷ͔͔͠ΓɺΠϕ ϯτΈ͍ͨͳେྔͷ୹ظϩδοΫ͕ऻͬͯ͘ΔαΠτ » ʢ͜͜·Ͱ͘ΔͱɺٯʹΦϨΦϨϑϨʔϜϫʔΫ͕ ૿͑࢝ΊΔ…ʣ

Slide 43

Slide 43 text

େମ͜͜Β΁ΜΛ·ͱΊΔͱ » ௒ॳ৺ऀ͸ϩάΠϯͳ͠ͷܝࣔ൘ » தɾ্ڃڃऀ͸Instagram΋Ͳ͖Λ࡞Δͱྑ͍ͱࢥ ͍·͢ » ͋ͳͨ͸FWͳ͠ͰͲ͜·Ͱॻ͚·͔͢ʁ » ॻ͚ͳ͍ʁ͡Ό͋وํʹ͸࣮Γ͕༗ΔνϟϨϯδ ʹͳΓͦ͏ʂ

Slide 44

Slide 44 text

ΦϨΦϨFWͱηΩϡϦςΟʹ͍ͭͯ » ΦϨΦϨ͔ͩΒͱආ͚ͯ௨Δ΂͖Ͱ͸ͳ͍ » ݹ͍FWͰΑ͋ͬͨ͘ϠόΠྫ » ύϥϝʔλΛͦͷ··ม਺ʹల։͢Δͱศརʂ » Ϣʔβʔͷೖྗ͸֬ೝը໘ͰνΣοΫͨ͠͠ɺhiddenΛͦͷ··Ϟ σϧʹ͍ΕΕ͹ศརʂ » อଘ͢Δςʔϒϧ໊ΛϢʔβʔೖྗ͔Βϓϧμ΢ϯͰબϕΔ͚Ͳɺϓ ϧμ΢ϯͰબ୒ࢶݻఆ͔ͩΒSQL૊Έཱͯʹ͔ͭ͑͹ศརʂ » URL͔ΒΫϥε΍ϝιου໊ΛҾͬுΕΔͱϧʔλʔෆཁͰศརʂ » ௕ظؒɺߏ଄Խ͞Ε໊ͨલ΍ΞΠίϯ౳ͷϩάΠϯ৘ใ഑ྻΛอଘ͠ ͍͚ͨͲserialize()Ͱจࣈྻʹͯ͠Cookieʹ͍ΕΔͱศརʂ

Slide 45

Slide 45 text

» ݹ͍ίʔυ͸ ౰࣌͸ΞϦͩͬͨ ϠόΠίʔυ͕͍ͬͺ ͍ɺਅࣅΔͱةݥ » Ͱ΋ɺʮ͜ͷίʔυ͸ةݥʯͱ͔Θ͔Βͳ͍͓… » ݹ͍ઃܭ͚ͩͲόʔδϣϯ͕ͪΌΜͱ্͕͍ͬͯΔ FWΛਅࣅ͠Α͏ʢ͋Δͷ͔ʁʣ » ษڧ͠·͠ΐ͏ » ಙؙຊ » աڈͷCVEΛͲΜͲΜಡΉ » (େม͚ͩͲ࣮ྫ͕ͲΜͲΜΘ͔Δ͠ɺલޙͷVerUpΛ ୳Ε͹࣮ࡍͷରࡦίʔυ͕Έ͔ͭΓɺ͓͢͢Ί)

Slide 46

Slide 46 text

΍͍͖ͬͯ·͠ΐ͏ » ܝࣔ൘͘Β͍ͳΒɺ๺ւಓͷτʔΫΛݟ͍ͯͩ͘͞ ʢ͕࣌ؒ଍Γ͵ʣ » ʮPHPerਓੜɺҰ౓͸ϑϨʔϜϫʔΫΛ࡞͓ͬͯ͜ ͏ʂʯ » https://speakerdeck.com/uzulla/phperren- sheng-du-hahuremuwakuwozuo-tuteokou

Slide 47

Slide 47 text

ͱ͍͏͜ͱͰɺ࣮ྫʢʁʣ঺հ » ࠷ԶʹΑΔɺԶͷͨΊͷฏ੒࠷ޙͷΦϨΦϨϑϨʔ ϜϫʔΫͷ͝঺հ͢ΔΑʂʂ » ʢޙͰࢿྉ͸UL͢ΔͷͰɺ੎͍ྑ͘ߦ͖·͢ʣ » ॳ৺ऀ޲͚ͬΆ͘ͳ͍࿩͕ଓ͖·͢ʂ͝ΊΜͳ͍͞ʂ

Slide 48

Slide 48 text

ܯࠂ » ओ؍͕ଟ͍ » ࢲ͸ࢲͷ՝୊͔͠ߟ͍͑ͯͳ͍ » ͋ͳͨ΋ओ؍Λ΋ͬͯ͑͑Μ΍Ͱʂͱ͍͏͜ͱͰ ͢ » Τϯλϝͱͯ͠ݟ͍ͯͩ͘͞ʂ

Slide 49

Slide 49 text

ݸਓతͳಈػ » ΊͪΌΊͪΌେख͔ɺϕϯνϟʔΈ͍ͨͳॴͷ࢓ࣄ͕ ଟ͍ » ༧ࢉʹγϏΞɺνʔϜͰͷೳྗࠩ͸ܹ͍͠ » ͔͠͠ଟ͘ͷ৔߹ɺܧଓͯ͠։ൃ͢Δ͜ͱ΋গͳ͍ » ͢͹΍͘ܖ໿ऴྃɾΫϏʹͳΔ » ͦͷޙɺεϙοτґཔ͕ଟ͍ » ͔͠͠ɺΞϓϦͷ໋͸݁ߏ௕͍

Slide 50

Slide 50 text

਺೥ޙʹ͘Δʮ͜Ε௚ͯ͠ʯ » ফඅ੫͕ɺ೥߸͕͔ΘΓ·ͨ͠ʙ » ݸਓ৘ใอޢ๏͕͔ΘΓ·ͨ͠ʙ » ܾࡁձࣾΛม͑·ͨ͠ʙ » αʔόʔҠసͯ͠PHPόʔδϣϯ୅ΘΓ·ͨ͠ʙ » S3ͷೝূ͕ʙ » APIΛ͸΍͍ͨ͠ΜͰ͢ʙ » ޙ೚͕ʹ͛·ͨ͠ʙ » (૬ख΋࢓ํͳ͘΍Β͟ΔΛಘͳ͍मਖ਼΋ଟ͍

Slide 51

Slide 51 text

ηΩϡϦςΟରԠ » ಥવग़ΔFWͷCVE » ʢ͓٬͕ʣίετΛ෷͑ͳ͍ » ͜Ε͕ʮᘥᙪʯ͔ͰᎍΊΔͭΒ͍ʂ » ʮFWબఆʹΑΔ੹೚ʯ͕໰ΘΕΔ͜ͱ΋

Slide 52

Slide 52 text

» ηΩϡϦςΟקࠂʹରԠ͢Δࣄ͕ʮηΩϡϦςΟʯͰ ͸ͳ͍…͕…ཁٻͱͯ͠͸ͦ͏ͳΓ͕ͪ » ͳ͓ʮബ͍ϑϨʔϜϫʔΫʯͩͱɺΞϓσͰ͖Δ ࣄ͕ଟ͍͕ͦΕ͸ηΩϡΞͱΠίʔϧͰ͸ͳ͍ » ࢓ํͳ͘ύον΍ϫʔΫΞϥ΢ϯυΛೖΕΔ » ϑϨʔϜϫʔΫʹϫʔΫΞϥ΢ϯυΛೖΕΔͱߦ ͖ࢭ·Γ » Ϗδωεʹ͓͍ͯ͜ͷίετΛʮݟࠐΉʯ͔ɺʮආ͚ Δʯඞཁ͕͋Δɻ

Slide 53

Slide 53 text

ྑ͍ϑϨʔϜϫʔΫͰղܾ͠ͳ͍ʂ » ςετͱɺςετ͕ݱ࣮తʹͰ͖Δਖ਼ؾͳઃܭ͕ॏཁ » FWͰϨʔϧ͔ΒམͪΔͷ͸؆୯ » ʮύϫʔϓϨΠʯͰʮҟৗͳཁ݅ʢओ؍ʣʯ͕͸͍Δ ͱɺͲΜͳϑϨʔϜϫʔΫͰ΋ऴΘΓ » ʮϥϐουʹߦ͚ΔʯFW΋ɺݱ৔ͰϥϐουΛڧ੍ ͞Ε͚ͭͮΔͱૣ൩ϥϐουʹ͍͚ͳ͘ͳΓ͕ͪ

Slide 54

Slide 54 text

ࡢࠓͷଟ༷ͳ؀ڥ΁ͷରԠ » όον΍ɺLambdaɺSwooleɾReactPHPΈ͍ͨͳมΘ࣮ͬͨߦ ؀ڥ » άάΔͱͰͯ͘Δɺී௨ͷFWͱͭͳ͙ʮΞμϓλʯͱ͍͏΍ͭ ͸ » ORM΍ίϯϑΟάɺDI͕࿩Λ΍΍͕ͪ͘͜͠͠ » ʮFW͔Β੾Γग़ͤ·͢Αʈʈʯʮ৴͡ͳ͍Αʂʯ » ʮ͏·͚͍ͤͬ͘͢Ε͹͍ͩ͡ΐ͏Ϳʯ͚ͩͲFWͷҙຯ͕ബ ͘ͳΔ » POPOʢPlain old PHP ObjectʣͩͱେମͲ͜ʹͰ΋͍͚࣋ͬͯΔ

Slide 55

Slide 55 text

ݸਓతͳ೰Έ·ͱΊ » ʮ̍Օॴ͔͑Ε͹ɺશ෦มΘΔʯΑ͘Ͱ͖ͨ'8͸࠷ ߴ » ͔͠͠ɺ೥୯ҐͰ͸όʔδϣϯΞοϓ͕ඞཁʢओ ؍ʣ » εϙοτ࡞ۀ͹͔ΓͰʮܧଓ͠ ͓͕ͯۚ΋Β͑ ͳ ͍ʯҊ݅Ͱ์ஔ͞ΕΔͱ٧Ή » ʮయܕతͳFWʯʹ൓߅͍͓ͨ͠೥ࠒʂ

Slide 56

Slide 56 text

» (Ұ෦ͷҊ݅Ͱ)FW΁ͷఘΊ » ڋ൱͍ͨ͠Θ͚Ͱ͸ͳ͍͕ɺൣғΛݮΒ͔͢ʁ » ͔ͦ͠͠ΕͰ͸FWͷҙ͕ٛ… » …Α͠ɺΦϨΦϨ͔ͳʂʢ࿦ཧͷඈ༂ʣ » (͜Ε͸ੈͷதͷΦϨΦϨFWͭ͘Δਓؒͷయܕత ͳݴ͍༁Ͱ͢ɻಉ྅͕͜͏͍͏͜ͱΛݴ͍ग़ͨ͠ ΒԥͬͯࢭΊ·͠ΐ͏) » (ಉ྅Ͱͳ͍ͳΒ(ྫ͑͹๻͕ݴ͍ग़ͨ͠Β)ɺͦͬ ͱ۪ஒΛฉ͍͍ͯ͋͛ͯͩ͘͞)

Slide 57

Slide 57 text

Α͠… » ʮ̍Օॴม͑Ε͹શ෦มΘΔʯ » ʮߴ͍ੜ࢈ੑʯ » ʮݟ௨͠ͷྑ͍ίʔυʯ » Λ࣮ݱ͢Δૉఢͳຐ๏Λࣺͯͯ… » ෺ཧͰΰϦԡ͠Ͱઓ͏ͧʂʂʂ

Slide 58

Slide 58 text

ͱ͍͏͜ͱͰΦϨΦϨϑϨʔϜϫʔΫΛ࡞Δͧʂ » ͋͘·Ͱ΋ݸਓతͳײ૝Ͱɺօ༷͸ͦ͏Ͱ͸ͳ͍͔ ΋͠Εͳ͍ɻ » ʢτʔΫͷྲྀΕ্ɺ͜͜͸ೲಘ͍ͩ͘͞ʣ » ʮͳΜͰ͋ΕɺΦϨΦϨ͸ͳ͍ͩΖʯͱ͍͏ͷ͸ਖ਼ ؾͳҙݟͰ͢ʢࢲ΋ී௨ʹී௨ͷϑϨʔϜϫʔΫ΋ ࢖͍·͢ʣ ͥͻͦͷ··͓͍࣋ͪͩ͘͞

Slide 59

Slide 59 text

Ore3 FW » https://github.com/uzulla/Ore3 » (Ore1,2͸લ࡞ͬͨͷͰ(҆қ)) » ༻్ɺJSON API » ໨ࢦ͢ॴ » ΤϥʔϋϯυϦϯά » ୯७͞ » αόΠϒੑʢओ؍ » ςετ͠΍͢͞

Slide 60

Slide 60 text

ʮαόΠϒʯͱ͸ʁ » Ͱ͖Ε͹ɺ<৽ݩ߸>5೥Ͱ΋ɺͪΐͬͱͷमਖ਼Ͱಈ͘ » ՄೳͳΒɺฏ੒ͷϥΠϒϥϦΛࢥ͍ग़͞ͳͯ͘ࡁΉ » ئΘ͘͹ɺ͔ͦ͜Βյͣ͞ʹमਖ਼Ͱ͖Δ » ख͕͔͔ؒͬͯ΋ɺ95%ͷέʔεͰ޻਺͕ಡΈ΍͢ ͍ɺϋϚΒͳ͍ » ։ൃதͷ࢓༷ύϫʔϓϨΠʹରԠͰ͖Δ

Slide 61

Slide 61 text

ࠓճͷΦϨΦϨFWʹ͓͚Δࡦ » ʮίʔυͷ֎ʯʹཔΔ͕ɺੜ੒͸͠ͳ͍ » *%&ͳͲπʔϧͷαϙʔτʢิ׬ɺ੩తղੳɺϦϑΝΫλػೳʣ Λ࠷େݶʹड͚ΒΕΔΑ͏ʹ » ੩తղੳ(ྫ:IDEͷInspect Code)ͷ׆༻ » ૉ๿ͳςετͷίετΛԼ͛Δ » ๨Εͯ΋͓͍͔͚ΒΕΔΑ͏ʹ » ҉໧ͷίʔυΛ΁Β͢(഑ྻΛҾ͖ճ͞ͳ͍ɺΫϥε΍ϓϩύςΟ Λ࡞Δ) » VCSͱͷ਌࿨ੑΛ্͛Δ(#MBNF͠΍͘͢ɺ%J⒎ΛΈ΍͘͢ ओ؍ )

Slide 62

Slide 62 text

ʮٯʹIDE౳ͷπʔϧͷຐ๏ʹཔͬͯͳ͍͔ʁʯ » ࠓޙIDEʢ΍PHPͷ੍໿ʣ͕؇Ήํ޲ʹਐ·ͳ͍ࣄʹ ౌ͚͍ͯΔ » ʮ…͜ΕPHPUnit͔ͭͬͯΔΑͶʁʯʮ΢οʯ

Slide 63

Slide 63 text

ࠓճ࡞ͬͨػೳ » ϧʔλʔ » Ϗϡʔ » ORM » DI

Slide 64

Slide 64 text

ࠓճ࡞ͬͨػೳʂ » ϧʔλʔ ͳ͠ ! » Ϗϡʔ ͳ͠ ! » ORM ͳ͠ ! » DI ͳ͠ !

Slide 65

Slide 65 text

࣮૷ͨ͠ػೳ͸ » ϦΫΤετ/Ϩεϙϯε ΦϒδΣΫτ » େҬͳΤϥʔϋϯυϦϯά

Slide 66

Slide 66 text

͓࡞๏(ػೳͰ͸ͳ͍) » ϦΫΤετɺϨεϙϯεͷ࡞๏ » σʔλɾϞσϧपΓͷ͓࡞๏

Slide 67

Slide 67 text

ϑΝΠϧߏ଄ !"" composer.json !"" api_real.php !"" shell.php !"" lib # $"" MyApp # !"" Api # # !"" Action # # !"" Request # # $"" Response # !"" Model # !"" Repo # $"" Service $"" tests # $"" testTest.php $"" vendor

Slide 68

Slide 68 text

!"" composer.json !"" api_real.php !" !"" shell.php !"" lib # $"" MyApp # !"" Api # # !"" Action # # !"" Request # # $"" Response # !"" Model # !"" Repo # $"" Service $"" tests # $"" testTest.php $"" vendor

Slide 69

Slide 69 text

api_realͷྲྀΕ » 0. Τϥʔϋϯυϥొ࿥ » 1. σΟεύον » 2. ϦΫΤετΦϒδΣΫτੜ੒(*Request.php) » 3. ΞΫγϣϯ࣮ߦ(*Action.php) » 4. (ΞΫγϣϯͷதͰ)ϨεϙϯεΦϒδΣΫτੜ ੒(*Response.php) » 5. ϨεϙϯεΦϒδΣΫτΛૹ৴

Slide 70

Slide 70 text

୯७Խͨ͠΋ͷ set_error_handler(/* ... */); // 0. Τϥʔϋϯυϥ try{ if($_SERVER['REQUEST_URI']='/'){ // 1. σΟεύν $req = new SomeRequest($_POST); // 2. reqੜ੒ $res = SomeAction::run($req); // 3. resੜ੒ }else{ /* ... */ } } // $res 4. Ϩεϙϯε $res->writeHeader($http_origin_header); // 5. ૹ৴ $res->writeBody();// 5. ૹ৴

Slide 71

Slide 71 text

0. Τϥʔϋϯυϥઃఆ౳-1 (গʑ؆ུԽͯ͠·͢ set_error_handler(function ($severity, $message, $file, $line) { throw new ErrorException($message, 0, $severity, $file, $line); }); register_shutdown_function(function () { $error = error_get_last(); if (!is_array($error) || !($error['type'] & (E_ERROR|E_PARSE|E_USER_ERROR|E_RECOVERABLE_ERROR))) { return; } // ਖ਼ৗऴྃܥ error_log("Uncaught Error: ..."); // Ωϟονͨ͠ΤϥʔΛϩά http_response_code(500); // response error header("Content-type: application/json"); echo json_encode([ "code" => 500, "message" => "internal server error" ]); }); // ࣍ͷεϥΠυʹଓ͘

Slide 72

Slide 72 text

0. Τϥʔϋϯυϥઃఆ౳-2 (গʑ؆ུԽͯ͠·͢ try { //લͷεϥΠυ͔Βଓ͘ ob_start(); require(__DIR__ . "/vendor/autoload.php"); // ========= ‼ ͜͜ʹΞϓϦίʔυ ‼ ============= ob_end_flush(); } catch (\Throwable $e) { // Uncaught Exception $error_class_name = get_class($e); error_log("Uncaught Exception {$error_class_name}: ..."); // ྫ֎Λϩά http_response_code(500); // response error header("Content-type: application/json"); echo json_encode([ "code" => 500, "message" => "internal server error" ]); }

Slide 73

Slide 73 text

» ϋϯυϥΛ࠷ॳʹઃఆ͠ɺNotice΋Warning΋ Ωϟονͯ͠ϩάˍΤϥʔը໘ » ΞϓϦશମ΋tryͰ͘͘ΓɺΩϟονͯ͠ϩάˍΤ ϥʔը໘ » ͜Ε͘Β͍΍Δͱศར » ͜ΕΛઆ໌͢Δͱ௕͘ͳΓ͗͢Δ…ͷͰলུ » ʢͦͷ͏ͪͲ͔͜Ͱ͜ͷ࿩͸͍ͨ͠Ͱ͢Ͷʣ

Slide 74

Slide 74 text

Output bufferͰ༧ظͤ͵ग़ྗΛ཈੍ ob_start();// Output bufferingΛ։࢝ $res = MyApp(); // ͜͜Ͱ͸ͳʹ΋ग़ྗ͠ͳ͍ɺ͋ͬͨΒΤϥʔ͔Կ͔ $something = ob_get_contents(); // ҙਤ͠ͳ͍ग़ྗ͕͋ͬͨΒϩά΁ if (strlen($something) > 0) { error_log($something); } ob_end_clean(); // (্Ͱϩάʹग़͍ͯ͠ΔͷͰɺࣺͯΔ) ob_start(); // ͔͜͜Β࣮ࡍʹૹ৴ $res->writeHeader($http_origin_header); $res->writeBody(); ob_end_flush();

Slide 75

Slide 75 text

» obଟ༻ͷ໨త͸ » ʮΤϥʔ࣌ʹ่Εͨग़ྗΛͩ͞ͳ͍͜ͱʯ » ʮ૝ఆ͍ͯ͠ͳ͍ग़ྗΛޡͬͯग़͞ͳ͍͜ͱʯ » ʮޡͬͯ200Λฦ͞ͳ͍͜ͱʯ » PHP͸ɺΤϥʔ౳Ͱ༧ظͤ͵ग़ྗ͕ग़Δͱૹ৴͞Εͯ͠· ͏ɺ͢Δͱϔομʔ΋ૹΕͳ͍ɺ͜Ε͸Web APIͩͱඍົ » ͳͷͰɺϨεϙϯεΦϒδΣΫτͰͷૹ৴Ҏ֎͸ɺશ෦ྫ ֎తͳ΋ͷͱͯ͠obͰ֬อͯ͠ϩάߦ͖ʹ͢Δɻ » var_dump()͕print debugͰ࢖͑Δͧʂศརʂ

Slide 76

Slide 76 text

࠶ܝࡌʣ୯७Խͨ͠΋ͷ set_error_handler(/* ... */); try{ if($_SERVER['REQUEST_URI']='/'){ $req = new SomeRequest($_POST); $res = SomeAction::run($re }else{ /* ... */ } } $res->writeHeader($http_origin_header); $res->writeBody();

Slide 77

Slide 77 text

1. σΟεύονͱ͍͏໊લͷifจ $request_uri = $_SERVER['REQUEST_URI']; $method = $_SERVER['REQUEST_METHOD']; $http_origin_header = $_SERVER["HTTP_ORIGIN"] ?? null; $base_uri = "/api"; $path = substr($request_uri, strlen($base_uri)); $path = explode("?", $path, 2)[0]; if ($method === "OPTIONS" && !is_null($http_origin_header)) { $res = new \MyApp\Api\Response\CORSPreFlightResponse(); } else if ($method === "GET" && $path === "/hello") { $req = new \MyApp\Api\Request\HelloRequest($_GET); $res = \MyApp\Api\Action\HelloAction::run($req); } else { $res = new \MyApp\Api\Response\Response(); $res->code = 404; }

Slide 78

Slide 78 text

» ʮ̎̌೥લ͔ͳʁʯ ʮύεύϥϝʔλΛ࢖Θͳ͚Ε͹͑͑Μ΍ʯ » ʢRESTfulͷ͜ͱΛߟ͍͑ͯͳ͍ʣ » ඞཁʹͳΕ͹ϧʔλʔΛೖΕΕ͹͍͍Ͱ͠ΐ » ʮpreg_matchͰ΋࣮ݱͰ͖ΔͰ͠ΐʢʁʁʯ » ྑ͍ϧʔλʔΛ͍Εͯ΋ɺେ఍ଟػೳΛ࢖Θͳ͍… » ελοΫτϨʔε͕ബ͍ʢϩά͕ݟ΍͍͢ʣ » ಥવݱΕͨ୹ظతͳṖ࢓༷ͷ૬ख͕Ͱ͖ΔɺϦΫΤε τΛ٧Ίସ͑ͯ͠ΞΫγϣϯΛίʔϧ͢Δͱ͔

Slide 79

Slide 79 text

࠶ܝࡌʣ୯७Խͨ͠΋ͷ set_error_handler(/* ... */); // 0. Τϥʔϋϯυϥ try{ if($_SERVER['REQUEST_URI']='/'){ // 1. σΟεύν $req = new SomeRequest($_POST); // $res = SomeAction::run($req); // 3. resੜ੒ }else{ /* ... */ } } // $res 4. Ϩεϙϯε $res->writeHeader($http_origin_header); // 5. ૹ৴ $res->writeBody();// 5. ૹ৴

Slide 80

Slide 80 text

!"" composer.json !"" api_real.php !"" shell.php !"" lib # $"" MyApp # !"" Api # # !"" Action # # !"" Request !" # # $"" Response # !"" Model # !"" Repo # $"" Service $"" tests # $"" testTest.php $"" vendor

Slide 81

Slide 81 text

2. ϦΫΤετΦϒδΣΫτ class HelloRequest extends Request implements RequestInterface { use ValidateRegexTrait; public $name; public function __construct(array $list) { $el = []; $result = $this->validateWithRegex($el, $list, 'name', "/\A[a-zA-Z0-9]{1,32}\z/u", true); $el = $result->error_list; $this->name = $result->val; $this->_error_list = $el; } }

Slide 82

Slide 82 text

» جຊ1ϧʔτʹ͖ͭɺ1Ϋϥε » ίϯετϥΫλʹ഑ྻ($_POST,$_COOKIE౳ʣΛ౉͢ » εʔύʔάϩʔόϧ͸ɺ͜ͷޙ͸Ұ੾࢖Θ͵੤͍ » ςετ࣌ʹָˍͦΕ͕ͳ͍ಛघ؀ڥͱͭͳ͗΍͘͢ » Ϋϥε͸༧ఆ͞ΕΔύϥϝλ෼ͷϓϩύςΟม਺Λ࣋ͭ » ϗϫΠτϦετͰ໌ࣔత » ޙड़ͷΞΫγϣϯ͸ɺϓϩύςΟม਺Λ௚઀৮Δ » *%&Ͱิ׬ɾ*OTQFDU͠΍͍͢ » ΧϓηϧԽ͕໨తͰ͸ͳ͍ͷͰpublic » ̍ʙׂ̎Ͱ࢖ΘΕΔϝιου͸ɺܧঝͰͳ͘Trait

Slide 83

Slide 83 text

!"" composer.json !"" api_real.php !"" shell.php !"" lib # $"" MyApp # !"" Api # # !"" Action !" # # !"" Request # # $"" Response # !"" Model # !"" Repo # $"" Service $"" tests # $"" testTest.php $"" vendor

Slide 84

Slide 84 text

3. ΞΫγϣϯ class HelloAction { public static function run(HelloRequest $req): ResponseInterface { if (!$req->isValid()) { return new ErrorResponse($req, 400, "bad request", $req->getErrorList()); } $name_san = NameSanService::getByName($req->name); return new HelloSuccessResponse($name_san); } }

Slide 85

Slide 85 text

» ͍ΘΏΔίϯτϩʔϥʔɺ੩తͳϝιουͰΑ͍ » Ҿ਺͸ϦΫΤετΦϒδΣΫτ » ฦΓ஋͸ResponseInterfaceΛ࣮૷ͨ͠΋ͷ » ޙड़ͷServiceΛୟ͖·͘ΓɺϨεϙϯεΛ࡞Δ

Slide 86

Slide 86 text

࠶ܝࡌʣ୯७Խͨ͠΋ͷ set_error_handler(/* ... */); try{ if($_SERVER['REQUEST_URI']='/'){ $req = new SomeRequest($_POST); $res = SomeAction::run($req); // ͜͜·ͰऴΘͬͨ }else{ /* ... */ } } // $res 4. Ϩεϙϯε ! $res->writeHeader($http_origin_header); // 5. ૹ৴ $res->writeBody();// 5. ૹ৴

Slide 87

Slide 87 text

!"" composer.json !"" api_real.php !"" shell.php !"" lib # $"" MyApp # !"" Api # # !"" Action # # !"" Request # # $"" Response !" # !"" Model # !"" Repo # $"" Service $"" tests # $"" testTest.php $"" vendor

Slide 88

Slide 88 text

4. Ϩεϙϯε class HelloSuccessResponse extends Response implements ResponseInterface { public $code = 200; public $name_san = null; public function __construct(NameSan $name_san) { $this->code = 200; $this->name_san = $name_san; } public function getBody(): string { return json_encode([ 'code' => $this->code, 'name_with_san' => $this->name_san->name ]); } public function writeBody(): void { echo $this->getBody(); } }

Slide 89

Slide 89 text

» ϨεϙϯεΦϒδΣΫτ΋ɺίϯετϥΫλͰʮ࣮ࡍʹඞཁͳ Ҿ਺ʯΛड͚औΔ » ͜͜Ͱ͸εΧϥʔͰ͸ͳ͘ɺϞσϧͷΫϥε໊ͰܕΛࢦఆ͢Δ » ϓϩύςΟʢ͜͜Ͱ͸$name_san)ʹ͸ϞσϧͷΠϯελϯε ΛೖΕ͓ͯ͘ » ֤छϞσϧΛϨεϙϯε·Ͱ࣋ͪࠐΉ͓࡞๏ͩͱɺtoArray લ͕ݟΕΔͷͰJSONΛ૬खʹจࣈྻςετͤͣʹࡁΉ » मਖ਼ൣғ͕ڱ͍ͷͰɺίϛοτϩά͔Β௥͍͔͚΍͍͢ ʢओ؍ʣ » ͜ͷ""ͱ͍͏ۭจࣈྻ్͕தͷΩϟετϛε͔ɺͦ͏Ͱͳ ͍͔൑அ͠΍͍͢ɺ౳ɻ

Slide 90

Slide 90 text

» get/writeBody()Ͱॴఆͷܗʹม׵͢ΔͷΛखͰॻ͘ » Ϩεϙϯεͷܗ͸Ϟσϧͷߏ଄ʹґଘͤ͞ͳ͍ » (ఆܗͷdefinitionͷ৔߹ʔͨͱ͑͹UserInfoͱ͔ʔ͸Ͳ͔͜ʹ toArray()ͱ͔ϔϧύΛ࡞Δࣄ΋͋Δ) » ӡ༻ϑΣʔζʹ͸͍Δͱɺςʔϒϧ͸ม͑ͳ͍͚Ͳݟͤํ͸͔ΘΓ͕ͪ » ಥવඇਖ਼نͳΧϥϜ͕૿͑Δ࣌ʹɺϞσϧ΍ActionΛ͍͡Βͳͯ͘ ΋ResͰٵऩͰ͖Δ » ྫɿ͋ΔAPI͚ͩauthor͕CSVͰ΄͍͠ʢ΄͔͸഑ྻͳͷʹ…ʣ » ྫɿ͜ͷϨεϙϯε͸Ձ֨ΛӅ͍ͨ͠ɺΫϩʔϧ͞Εͨ͘ͳ͍ » ʮ͜ͷ࢓༷Ͱ߹ҙ͕ͱΕͨΜͩɺ͔ͩΒே·Ͱʹ࡞ͬͯʯ » ͋Δ͍͸ɺϞσϧ͕͔Θͬͯ΋API࢓༷ΛഁյͰ͖ͳ͍

Slide 91

Slide 91 text

» ͜ͷΫϥεʹૹ৴ʢechoʣ͢Δίʔυ͕͋Δ » body͕ڊେͳόΠφϦͳΒɺ͜͜ͰҰ୴obΛ͸ͣ͢ ͳͲ޻෉͕Ͱ͖Δ » ͦͷͨΊɺʮඞཁʹԠͯ͡ʯResʹStream΍ GeneratorΛΘͨͯ͠Α͍

Slide 92

Slide 92 text

4. Ϩεϙϯε(ϔομʔؔ࿈) ؆ུԽͯ͠·͢ class Response implements ResponseInterface { public $code; protected $header_list = [ "Content-type" => "application/json" ]; protected $cookie_list = []; public function __construct($code, $name){ $this->code = $code; } public function writeHeader(string $http_origin = null): void { foreach ($this->getHeader($http_origin) as $key => $val) { header(sprintf("%s: %s", $key, $val)); // ϔομૹ৴ } foreach ($this->cookie_list as $cookie) { CookieService::setCookie($cookie); // ΫοΩʔૹ৴ } http_response_code($this->code); // Ϩεϙϯείʔυηοτ /* ... */

Slide 93

Slide 93 text

» ϔομʔ΍ΫοΩʔ͸ಉ༷ʹϓϩύςΟʹʢ഑ྻͱ͠ ͯʣ΋ͭɻ » cookieͳΜ͔͸CookieͷϞσϧͰ͸͍͍ͬͯΔ » ςετͷͨΊʹ » ࣮ࡍʹwriteHeader͢Δ·Ͱ͸ૹ৴͠ͳ͍ » writeBodyಉ༷ʹɺ௚઀ϔομʔΛૹ৴͢Δίʔυ Λ͜͜ʹॻ͘ » Etag΍TTLͱ͔ɺPrivateɺno-cacheΈ͍ͨͳͷ΋ ॻ͘

Slide 94

Slide 94 text

5. api_realʹ΋Ͳͬͯૹ৴ set_error_handler(/* ... */); try{ if($_SERVER['REQUEST_URI']='/'){ $req = new SomeRequest($_POST); $res = SomeAction::run($req); }else{ /* ... */ } } $res->writeHeader($http_origin_header); // 5. ૹ৴ $res->writeBody();// 5. ૹ৴

Slide 95

Slide 95 text

» ࠷ޙͰResͷwriteHeader/Body͕ݺ͹ΕΔ » writeHeader()Ͱϔομʔ(CORSܥ΍Content- typeɺExpire΍Attachment)/ΫοΩʔΛૹ৴ » writeBody()͕σʔλΛૹ৴ʢechoʣ » ʢgetBody/Header()͸جຊతʹ͸ςετͷͨΊʹ͋ ΓɺwriteBody()͔ΒgetBody()΁ͷݺͼग़ؔ͠܎͸ ڧ੍͠ͳ͍ɺͪΐͬͱ໊෇͚͕ඍົ…ʣ

Slide 96

Slide 96 text

͸͍ » ܕ͕ଟ͍ » ໌ࣔ » %*Λ࢖Θͳ͍

Slide 97

Slide 97 text

ͭΒ͍ͱ͜Ζʢଞਓͷ૝૾ʣ » ίʔυ͕ଟ͍ » IDEͱͰ͔͍Ϟχλʔਪ঑ » मਖ਼Օॴ͕ଟ͍ » ҰൃͰόʔϯʂͬͯͳΒͳ͍ » IDE͔ͭͬͯͳ͍ͱॻ͖ଛ͕͡ଟ͍ » ϦϑΝΫλ΋IDE͕ͳ͍ͱͭΒ͍ » ແ৺Ͱॻ͖׵͑ΔࠜੑϓϨΠ

Slide 98

Slide 98 text

ଓ͍ͯɺσʔλपΓͷن໿ະ ຬɺ͓໿ଋ…͸ࠓճεΩοϓ » σʔλͷߏ଄…ͳΜͰ͕͢ » ͞Βʹॳ৺ऀͷܕ…͍΍ํΛஔ͖ڈΓʹ͢Δಠળ తɾಠΓΑ͕Γͳ಺༰ » 30෼ͷτʔΫͰ͸͓ΘΒΜͷͰεΩοϓ͠·͢ʂ ʢ͓ΘΓʹ͚͓͖ͭͯ·͢ʣ » ޙͰΈͳ͞ΜࢿྉΛΑΜͰͶʂ

Slide 99

Slide 99 text

͸͍

Slide 100

Slide 100 text

Ore3 ·ͱΊ » ੩తղੳπʔϧ͔ΒཧղͰ͖ΔΑ͏ʹ » ܕΛՄೳͳݶΓॻ͘ » DIͳ͠ » ʮઃఆϑΝΠϧʯ͸࠷খݶʹ » ςετͷखؒΛ΁Β͢ » ೖྗͱग़ྗͷςετΛॻ͖΍͘͢ʢओ؍ʣ » PHPຊମͷػೳ͸ૉ௚ʹ͔ͭ͏

Slide 101

Slide 101 text

» ܽ఺͸΋ͪΖΜमਖ਼ൣғ͕޿͘ͳΔ͜ͱ » IDEͱςετͰࠜੑͰ۪௚ʹ࣏͢ » ςετ΍ܕͰɺ੔߹ੑΛ୲อ͍ͯ͘͠ » ʮ͜ΕFWͷҙຯ͋Δʁʯ » ͔͠͠मਖ਼࣌ؒΛݟੵ΋Γ͠΍͍͢ʢओ؍ʣ » 90%ͷཁ݅Λ̍࣌ؒͰ௚ͤΔ୅ΘΓʹ10%Ͱ͸ϋϚͬͯҰि ͔͔ؒΔΑΓɺ95%͕̍ప໷ͰऴΘͬͯ΄͍͠ʢओ؍ʣ » ಥવJOINͱ͔UNIONඞཁʹͳΔͱORMΉ͔ͣ͗ͯ͢͠ ʮSQL͔͔ͤͯ͘ΕʂʂʯͱͳΔʢษڧෆ଍ʣ » ORMͷΉ͔͍ͣ͠࢖͍ํ͸๨Ε͕ͪɺSQLͩͱ͙͢ʹΘ͔ Δ…ʢ࿝ਓʣ

Slide 102

Slide 102 text

» ʮδϟόͰ͍͍ͷͰ͸ʁʯʮsorry, I am PHPerʯ » ʮhackͰ͍͍ͷͰ͸ʁʯʮhackʹPHPStorm΄͠ ͍ʯ » Typed Properties͖ͯ΄͍͠ʂࠓ͙͢ʂ » Enum͖ͯ΄͍͠ʂࠓ͙͢ʂ » listड͚͍ͨ͠ʂδΣωϦΫεʂ » (େମ͜͏͍͏ͷHackʹ͋ΔΜͩΑͳΝ) » ·͋ɺࢲ͸PHPerͳͷͰ

Slide 103

Slide 103 text

» ͍ͩͿʮࣗݾத৺తʯͰ͢ͶɺΦϨΦϨײ͋Δʂʂ

Slide 104

Slide 104 text

݁ՌɺͲ͏ͳ͔ͬͨʁʢϑΟ ΫγϣϯͰ͢ » ʮࢲ͸ʯ޻਺͕ΑΊΔΑ͏ʹͳͬͨ(ओ؍) » IDE͕͋Ε͹ɺ(ςετ͢Δ·Ͱ΋ͳ͘)suspectsͰׂ ͷϛεʹؾ͚ͮΔΑ͏ʹ » (IDE΍ςετΛ͠ͳ͍ਓͱ΍Δͱ)ίʔυमਖ਼ɾϨ Ϗϡʔෛՙ্ঢ » ·͋ɺࢲ͕੹೚ͱΔʢ؃औΔʣҊ݅ͳͷͰେৎ෉(?)

Slide 105

Slide 105 text

٘ਜ਼͸ͳʹ͔ʁ » ଞਓ͔Βݟͨʮ͓͠ΌΕʯ͞ » ʢΧʔΰɾΧϧτΛ৴͡Δʣࣗ෼ͷࣾձੑ » ̍ՕॴΛม͑Δͱશ෦͕׬੒͢ΔΑ͏ͳମݧ » ػցʢIDEʣʹͨΑΒͳ͚Ε͹ಡΊͳ͍ » ػցʢςετʣʹͨΑΒͳ͚Ε͹݈શ͔Θ͔Βͳ͍

Slide 106

Slide 106 text

͸͍

Slide 107

Slide 107 text

͜Ε͸FWͳͷ͔ʁ » ͜Μͳػೳ͕͘͢ͳ͍͍ͯ͘ͷ͔ʁ » ͍΍͍΍ɺࢲʹ͸͜Ε͸FWͰ͢Α » ίʔυͷଟՉ͕FW͔Ͳ͏͔Ͱ͸ͳ͍ʢ̍πΠʔτ ʹೖΔFWͳͲ͋ΔΘ͚Ͱʣ » FWͱ͸ίʔυͷ࣮ମͰ͸ͳ͍ʂελΠϧͰ͋ Δʂʢओ؍

Slide 108

Slide 108 text

ͱ͍͏͜ͱͰΦϨΦϨFWͷ ঺հͰͨ͠ʂ » ੈքͷย۱ʹ͸͜͏͍͏ߟ͑ํ΋͋Δʂ

Slide 109

Slide 109 text

ॳ৺ऀ޲͚·ͱΊ » FW࡞Δͷ͸ͨͷ͍͠ʂͰ΋ͦͷखؒͰΞϓϦ͕࡞ΕΔ ͧʂʂʂ » ࡞Δ΋ͷ͕ʰੈͷதͷ80%ͷ΢ΣϒΞϓϦʱͳΒɺͨ͠ ͔ʹʰ80%ʹ޲͍͍ͯΔϑϨʔϜϫʔΫʱΛ࢖͏΂͖ » ΦϨΦϨ͸ࣗ෼ࣗ৴΍<৽ݩ߸>ʹjoinͨ͠νʔϜϝΠ τʹ࠘·ΕΔͧʂʂ » झຯͷൣғʹ͠·͠ΐ͏ » ʮ࢖͍ํʯҎ֎΋ֶ΅͏

Slide 110

Slide 110 text

தڃऀ޲͚·ͱΊ » ͝ଘ஌ͷ௨Γ(?)ʮϝδϟʔͳFWΛ͔ͭͬͨΒສࣄղܾʯ͠ͳ͍͕ɺ ਏͯ͘΋͕Μ͹Δͷ͕ਖ਼͍͠ಓͩ » ͢Ͱʹ͋Δ஌ݟɾઃܭɾϥΠϒϥϦΛ୳͠ɺֶ΅͏ » ͨͩɺڝ߹ͱಉ͡Ͱڝ૪ͰউͯΔͷ͔ʁ » FWΛʮ৐Γ׵͑Δʯͱ͍͏ߦҝࣗମ͕͔ͳΓܦݧ͕ͨ·ΔͷͰἚͷ ಓΛΏ͜͏ » ΦϨΦϨFW͔Β୤٫Ͱ͖Δɺ͋Δ͍͸ΦϨΦϨFWʹҠߦͰ͖Δ ઃܭ » ʮࠓͲ͖͸͜Εͩʂʯͱ͔ࣖ೥૿ʹͳΔͱɺPHPerϥΠϑͷָ͠͞ ͕൒ݮͯ͠͠·͏ͧʂΈΜͳΦϨΦϨͯ͠Δʂ܅΋ΦϨΦϨ͠Α͏ʂ

Slide 111

Slide 111 text

্ڃऀ޲͚·ͱΊ » ʮ͜Μͳ͜ͱ͍ͬͯΔ͚ͲΦϨΦϨ͕̑೥͔࣋ͭʁʯ ʮͦΕͳʯ » ୤ग़͸ݟࠐΜͰ͓͔͘͠ͳ͍͠ɺͦͷͨΊʹ͸ۃྗ ෼཭Մೳʹ͠ɺγϯϓϧʹ͍͖͍ͯͨ͠ » Ҡॅ͕Ͱ͖ΔͳΒɺͲΜͳFWͰ΋ɺΦϨΦϨͰ΋͓ ͦΔΔʹ଍Βͣʢͦ͏͔ʁʁʣ » ࢲ৴ɿΠέͯΔSQLBuilderΛ͕͚͍ͭͮͯ͞͠·͢

Slide 112

Slide 112 text

·ͱΊ » ʮϚδϣϦςΟʢʁʣʯΛ໡৴ͯ͠·ͤΜ͔ʁ » ׳ྫΛٙ͏ͷ͸ॏཁ » ʢതଧͱͯ͠͸ɺϚδϣϦςΟͷํ͕҆ṛ͚ͩͲʂʣ » ʮ͍͍͜ͱݴͬͯΔʯ෩ͳҙݟΛ৴͡Δͳʢʁʁʁ » #΍ͬͯΈΑ͏ͥ » ͱ͍͏͜ͱͰɺΈΜͳ ࣗ͝୐Ͱ ΦϨΦϨϑϨʔϜϫʔ ΫΛ͍ͭͬͯ͘͜͏ͳʂʂΦϨʹ΋Έͤͯ͘Εʂʂ

Slide 113

Slide 113 text

׬

Slide 114

Slide 114 text

܁Γฦ͠ » #ΦϨΦϨϑϨʔϜϫʔΫ ͸·ͣ͸झຯͰ΍Ζ͏ͳʂʂ

Slide 115

Slide 115 text

ʮͳͥPSR-7(౳)Ͱ͸ͳ͍ͷ͔ʁʯ ʮͳͥReq/ResΛ࠶ൃ໌ͨ͠ͷ͔ʁʯ » ݁ߏ࢖ͬͨΜͰ͚͢Ͳ…ίʔυ͕௕͘ͳΓ͕ͪʂςετਏ͍ » psr7͸http༻ͳͷͰɺࠓࣗ෼͕΄͍͠΋ͷΑΓϩʔϨϕϧ » ·ͩࢫຯ͕গͳ͍ʂ » ·͋ɺpsr7͕ඞཁʹͳΕ͹Ξμϓλॻ͚Δ » Req/ResͰܕΛ͠͹Γ͍ͨཉ͕͋ͬͨ » psr7Λجఈʹ֦ͯ͠ுͮ͠Β͗͢ΔͰ͠ΐ… » ࢓༷ύϫʔϓϨΠରॲͷ୤ग़ϋονΛ࡞ΓͮΒ͍

Slide 116

Slide 116 text

σʔλ » Service, Repo, Modelͷࡾ૚ » Service: Model/RepoΛ·͙ͨॲཧɺτϥϯβΫ γϣϯΛఆٛͰ͖Δ » Repo: SQLΛॻ͘ʢʂʣɺModelΛฦͨ͠ΓɺӬଓ Խ » Model: ໨తͱͯ͠͸ߏ଄ମɺ͍ΖΜͳॴͰҾ਺ͷܕ ͱͯ͠ࢦఆɻ->isEqual($val)ɺ->toArray()ͱ͔ ΦϒδΣΫτΒ͍͠؆୯ͳϩδοΫ΋ؚΉ

Slide 117

Slide 117 text

Service !"" lib # $"" MyApp # !"" Api # # !"" Action # # !"" Request # # $"" Response # !"" Model # !"" Repo # $"" Service !" $"" tests # $"" testTest.php

Slide 118

Slide 118 text

class UserAccountService { public static function getByEmail(string $email, UserAccountRepo $repo=null): ?UserAccount { $repo = $repo ?? new UserAccountRepo(); return $repo->getByEmail($email); } public static function getByEmailAndPassword(string $email, string $password, UserAccountRepo $repo): ?UserAccount { $ua = static::getByEmail($email, $repo); if (is_null($ua)) return null; if (!password_verify($password, $ua->hashed_password)) return null; return $ua; } public static function update(UserAccount $ua, UserAccountRepo $repo = null): bool { $repo = $repo ?? new UserAccountRepo(); return $repo->update($ua); }

Slide 119

Slide 119 text

» ੩తϝιουͷմ » Action͔Β͸repoΛ৮Βͣɺ͜ΕΛ৮Δ » ϔϏʔͳ໰͍߹Θ͕ͤൃੜ͢Δ৔߹͸ΩϟογϡΛ͜ ͜ʹೖΕΔ͜ͱ΋ » Modelͱ1:1ʹͳΒͳ͍ɺModelʹରͯ͠ෳ਺ͷ Service͕͋Δ͜ͱ΋͋Δ͠ɺService͕ෳ਺ͷ ModelΛૢ࡞͢Δ͜ͱ΋͋Δɻ » Service͔ΒServiceΛ৮Δࣄ΋͋Δ

Slide 120

Slide 120 text

Repo !"" lib # $"" MyApp # !"" Api # # !"" Action # # !"" Request # # $"" Response # !"" Model # !"" Repo !" # $"" Service $"" tests # $"" testTest.php

Slide 121

Slide 121 text

class UserAccountRepo extends DB { public function getByEmail(string $email): ?UserAccount { $pdo = static::getPdo(); $stmt = $pdo->prepare("SELECT * FROM `user_account` WHERE email = :email"); $stmt->bindValue('email', $email, \PDO::PARAM_STR); $stmt->execute(); $stmt->setFetchMode(\PDO::FETCH_CLASS, '\MyApp\Model\UserAccount'); return $stmt->fetch() ?: null; } public function create(UserAccount $ua): int { if(!$ua->isValid()) throw new \InvalidArgumentException("invalid user account model"); $pdo = static::getPdo(); $stmt = $pdo->prepare(" INSERT INTO user_account (email, hashed_password, name) VALUES (:email, :hashed_password, :name) "); $stmt->bindValue('hashed_password', $ua->hashed_password, \PDO::PARAM_STR); $stmt->bindValue('name', $ua->name, \PDO::PARAM_STR); $stmt->bindValue('email', $ua->email, \PDO::PARAM_STR); $result = $stmt->execute(); if (!$result) throw new \RuntimeException("DB query error."); return $pdo->lastInsertId('id'); }

Slide 122

Slide 122 text

» ӬଓԽ΍σʔλͷϩʔυΛ࢘Δ » ModelΛੜ੒ͨ͠ΓɺModelΛอଘͨ͠Γ͢Δ » όϦόϦʹSQLΛॻ͍ͯ΋͍͍͠ɺ֎෦APIΛୟ͘ࣄ ΋͋Δ » ϛεϚονΛٵऩ͢Δ » ྫ֎͸جຊ࢖Θͳ͍ɺ0݅औಘͱ͔͸جຊNULLฦ͠ Ͱ্ҐͰڍಈΛ൑ఆ͢Δ » Goͷval, errorΈ͍ͨͳͷ΄͍ͬ͢͠Ͷ… listड ͚Ͱ΋͍͍͚Ͳ…ɻ

Slide 123

Slide 123 text

» setFetchMode(\PDO::FETCH_CLASS, UserAccount::class);Λଟ༻ » SQLΛੜ੒͠ͳ͍Ͱ͢Ή୯ͳΔ̍ߦηϨΫτ͸SQLख ॻ͖ » SQL͸10೥ઓ͑ΔͷͰ » ෳࡶͳʢͨͱ͑͹ݕࡧʣΫΤϦ͸ݫ͍͠ͷͰSQLϏϧ μ΋࢖͏ » nilportugues/php-sql-query-builder » บ΋ଟগ͋Δ͕ɺਖ਼௚ɺܾఆ൛͕ݟ͔ͭΒͳ͍

Slide 124

Slide 124 text

Service !"" lib # $"" MyApp # !"" Api # # !"" Action # # !"" Request # # $"" Response # !"" Model !" # !"" Repo # $"" Service $"" tests # $"" testTest.php

Slide 125

Slide 125 text

Modelྫ class UserAccount { public $id = 0; public $email = ""; public $hashed_password = ""; public $name = ""; public function __construct() { if ($this->id === 0) return; // PDO fetchͳΒҎ߱΋࣮ߦ͞ΕΔ $this->id = (int)$this->id; } public function getPublicData(): array { $list = get_object_vars($this); unset($list['id']); unset($list['hashed_password']); return $list; }

Slide 126

Slide 126 text

» ཉ͍͠σʔλߏ଄͕͋Ε͹ͭ͘ΔɺςʔϒϧͱҰରҰͰ ରԠඞਢͰ͸ͳ͍ » ϓϩύςΟ͸ඞཁͳ෼ͭ͘ΔɺIDEͷิ׬ʹ΋͔ͭ͏ » ଟ͘ͷέʔεͰ͸ɺίϯετϥΫλ͸FETCH_CLASSܦ༝ Λ૝ఆɺศརʂ » PDO FETCH_CLASS͸શ෦strʹͳΔͷͰɺModelͷίϯ ετϥΫλͰม׵ɺ͍ͩ͞ » Typed Properties͕͖ͨΒઈରʹ͜͜Ͳ͏ʹ͔ͳͬ ͯͯ΄͍͠… » ͳ͓ɺhydrate΋(΍Ζ͏ͱ͓΋͑͹)͜͜ͰͰ͖Δ

Slide 127

Slide 127 text

// ଓ͖ public function setPassword(string $new_plain_password): void { $this->hashed_password = password_hash($new_plain_password, PASSWORD_DEFAULT); } public function passwordVerification(string $plain_pass): bool { return password_verify($plain_pass, $this->hashed_password); } public function isValid(): bool { return count($this->validate()) === 0; } public function validate(): array { /* ... লུ ... */ return []; // is OK }

Slide 128

Slide 128 text

» ͋·Γϝιου͸ੜ΍͞ͳ͍Ͱ͓͘ɺຊ౰ʹ࠷௿ݶ ͷΈॻ͘ » Ϋϥε಺Ͱด͡ΒΕΔΑ͏ͳ؆୯ͳϢʔςΟϦςΟత ͳϝιου͸͜͜ʹੜ΍ͯ͠΋ྑ͍ » generate_uuid,base64url_encode,validate…

Slide 129

Slide 129 text

σʔλ·ͱΊ » ͱʹ͔͘ܕΛ͚ͭΔ » ྫ֎͸࠷௿ݶʢओ؍ʣ » ฦΓ஋ʹNULLଟ༻͸ɺݹ͍ਓؒͳͷͰؾʹͳΒ ͳ͍ ?Type Έ͍ͨʹ͢Ε͹͍͍͠ » ʢGoΈ͍ͨʹ(v, err)͍ͨ͠…ʣ

Slide 130

Slide 130 text

ඒ࣮͘͠૷͍ͨ͠Θ͚Ͱ͸ͳ͍ » ϦϑΝΫλϦϯάͰյΕʹ͍ͨ͘͘͠ » Ͱ͖Δ͚ͩґଘΛ୯ํ޲ʹʢඞͣɺͰ͸ͳ͍ʣ » मਖ਼ͷӨڹ͕޿͘ग़Δ(Ͱͯ͠·͏)ARύλʔϯʹ͸͠ͳ͍ ʢঢ়ଶ͸Ͱ͖Δ͔͗Γ࣋ͨͤͳ͍ɺ͔͠͠Ϧιʔε͕…ʣ » ΄Μ΋ͷͷDataMapper͸ͭΒ͍͆ʢ͋͋ɺΦϨΦϨͩ… » ϔϯςίͳHugeͳ࢓༷͕ଞΛߥΒ͞ͳ͍Α͏ʹ͍ͨ͠ » ҟৗͳཁ͕݅ύϫʔϓϨΠͰ͖ͨΒɺ BookInsaneSearchRepoͱ͔ͭͬͯ͘ղܾ͢Δ » ਖ਼ؾͳۭؾʹͳͬͨΒɺࣺͯΔʢͯ͢ΒΕΔͷ͔ʁʣ

Slide 131

Slide 131 text

» ʢҰൠతͳʣFWͰ΍Δͱɺ΍Γํ͕Θ͔Βͳ͔ͬͨ Γɺศརػೳ͕͔ͭ͑ͳͯ͘͏Μ͟Γ » Θ͔ΒΜʂͱͳͬͯ҆қʹ഑ྻʹม׵ͪ͠Όͬͯ ޙͰഁ໓ʢ͜Ε͸ࢲͷษڧෆ଍ͩʣ » ԕྀͳ͘ɺςʔϒϧ͸ͦͷ··ͰModelʢͱɺR ͱSʣΛ૿΍ͯ͠ରԠ͢ΔɺSQLॻ͘ » (γϯϓϧͳSQL Builderಉ༷ʹɺγϯϓϧͳ Hydrater΄͍͠Ͱ͢Ͷ) » Ϟσϧ,DB,(APIͷ)JSONߏ଄Λ߹ΘͤΔن໿ʹҰ୴ ͞ΑͳΒ

Slide 132

Slide 132 text

» DB(PDO)ΛૉखͰ͔͍͍ͭͨ࣌ʹORM͸͠ΜͲ͍ » ී௨ͷORM͸ςʔϒϧͷΧϥϜͷ૿ݮʹ͸ରԠ͠ ΍͍͕͢ɺӡ༻ϑΣʔζͰ͸ςʔϒϧͷΧϥϜͦ Μͳʹ૿ݮ͠ͳ͍ؾ͕͢Δʢओ؍ʣ » γϯϓϧͳΫΤϦ͸ΫΤϦϏϧμͷඞཁੑ͕͋Μ ·Γͳ͍ » ΫΤϦϏϧμ͕bindValueͷܕΛͪΌΜͱ͋ͭ ͔ͬͯ͘Εͳ͍͜ͱ͕ଟ͍… » ʮ͑ͬɺ͜ΕͲ͔͜ΒͲ͜·ͰτϥϯβΫγϣϯͳ ͷʁϩʔϧόοΫ͸ʁʯ

Slide 133

Slide 133 text

» ViewɺController૚͸৐Γ׵͑΍͍͢ɺಉ͡ϨΠϠ Ͱͷґଘ͕͘͢ͳ͍ » ʢ͍ΘΏΔʣModel͸ॎஅɺԣஅతʹґଘ͢Δ͜ͱ ʹͳΓ͕ͪɺ͜͜͸ૈ৯ʹͨ͠΄͏͕௕ੜ͖ʹ͖͘ ͧʢओ؍