Slide 1

Slide 1 text

Laravel Ͱ΍ͬͯΈΔ ΫϦʔϯΞʔΩςΫνϟ PHP Conference Fukuoka 2019 @okashoi WILLGATE, Inc.

Slide 2

Slide 2 text

͸͡Ίʹ • εϥΠυ͸ެ։ࡁΈͰ͢ • ࣸਅ౳΋׻ܴͰ͢ 🙆 • ײ૝ɾϑΟʔυόοΫ౳͓଴͍ͪͯ͠·͢ʂ • ϋογϡλά #phpconfuk #hall_fu 2

Slide 3

Slide 3 text

໨࣍ • ͜ͷτʔΫͷΊ͟͢ͱ͜Ζʢ2 ෼ʣ • ΫϦʔϯΞʔΩςΫνϟͷ֓ཁʢ3 ෼ʣ • ίΞͱͳΔߟ͑ํʢ5 ෼ʣ • ۩ମతͳίʔυྫʢ10 ෼ʣ • ·ͱΊʢ3 ෼ʣ • ࣗݾ঺հʢ2 ෼ʣ 3

Slide 4

Slide 4 text

໨࣍ • ͜ͷτʔΫͷΊ͟͢ͱ͜Ζʢ2 ෼ʣ • ΫϦʔϯΞʔΩςΫνϟͷ֓ཁʢ3 ෼ʣ • ίΞͱͳΔߟ͑ํʢ5 ෼ʣ • ۩ମతͳίʔυྫʢ10 ෼ʣ • ·ͱΊʢ3 ෼ʣ • ࣗݾ঺հʢ2 ෼ʣ 4

Slide 5

Slide 5 text

͜ͷτʔΫͷΊ͟͢ͱ͜Ζ🏁 • ΫϦʔϯΞʔΩςΫνϟͷίΞͱͳΔߟ͑ํ • ͦΕΛ࣮ݱ͢ΔͨΊͷ۩ମతͳίʔσΟϯά • ͦΕΒΛ࣮ફ͢Δ্Ͱͷ Laravel ͱͷ෇͖߹͍ํ ͜ΕΒΛ஌ͬͯ΋Β͍ɺͦͷҰ෦෼͚ͩͰ΋
 ͜Ε͔Βͷ։ൃʹ׆͔ͯ͠΋Β͏ 5

Slide 6

Slide 6 text

͜ͷτʔΫͰ࿩͞ͳ͍͜ͱ🙅 • Laravel ͷػೳͷղઆ • ʰΫϦʔϯΞʔΩςΫνϟʱʹग़ͯ͘Δ֓೦ ͷৄࡉͳղઆ 6

Slide 7

Slide 7 text

໨࣍ • ͜ͷτʔΫͷΊ͟͢ͱ͜Ζʢ2 ෼ʣ • ΫϦʔϯΞʔΩςΫνϟͷ֓ཁʢ3 ෼ʣ • ίΞͱͳΔߟ͑ํʢ5 ෼ʣ • ۩ମతͳίʔυྫʢ10 ෼ʣ • ·ͱΊʢ3 ෼ʣ • ࣗݾ঺հʢ2 ෼ʣ 7

Slide 8

Slide 8 text

ݪయ 8 2017 ೥ॳ൛ൃߦ 2018 ೥ॳ൛ൃߦ

Slide 9

Slide 9 text

ΫϦʔϯΞʔΩςΫνϟͷਤ ग़యɿ”The Clean Architecture - The Clean Code Blog”, https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html 9

Slide 10

Slide 10 text

ΫϦʔϯΞʔΩςΫνϟͷਤ • ΫϦʔϯΞʔΩςΫνϟʹ͍ͭͯௐ΂Δͱ
 ·ͣ໨ʹ͢Δਤ • ຊτʔΫͰ͸֤૚ͷৄࡉͳղઆ͸͠ͳ͍ • ͜ͷਤʹ஧࣮ʹ࣮૷͑͢͞Ε͹Α͍ɺͱ͍͏ Θ͚Ͱ͸ͳ͍ 10

Slide 11

Slide 11 text

ԿΛ໨తͱ͍ͯ͠Δ͔ʁ • ಠཱ։ൃՄೳ • ಠཱσϓϩΠՄೳʢ˞ʣ • ςετՄೳ ※ PHP ։ൃʹ͓͍ͯ͸Πϝʔδ͠ʹ͍͔͘΋ 11

Slide 12

Slide 12 text

“ιϑτ΢ΣΞΞʔΩςΫνϟͷ໨త͸ɺ
 ٻΊΒΕΔγεςϜΛߏஙɾอक͢ΔͨΊʹ ඞཁͳਓࡐΛ࠷খݶʹ཈͑Δ͜ͱͰ͋Δɻ” 12

Slide 13

Slide 13 text

໨࣍ • ͜ͷτʔΫͷΊ͟͢ͱ͜Ζʢ2 ෼ʣ • ΫϦʔϯΞʔΩςΫνϟͷ֓ཁʢ3 ෼ʣ • ίΞͱͳΔߟ͑ํʢ5 ෼ʣ • ۩ମతͳίʔυྫʢ10 ෼ʣ • ·ͱΊʢ3 ෼ʣ • ࣗݾ঺հʢ2 ෼ʣ 13

Slide 14

Slide 14 text

ίΞͱͳΔߟ͑ํ ʮॏཁͳ΋ͷʯΛʮࠣࡉͳ΋ͷʯʹґଘͤ͞ͳ͍ 14

Slide 15

Slide 15 text

ॏཁͳ΋ͷʁ 15 σʔλϕʔε ϑϨʔϜϫʔΫ ςετ 6* 8FC 03.

Slide 16

Slide 16 text

ॏཁͳ΋ͷʁ 16 σʔλϕʔε ϑϨʔϜϫʔΫ ςετ 6* 8FC 03. 🙅 ⾠͋͘·ͰΫϦʔϯΞʔΩςΫνϟͷจ຺ͷ࿩

Slide 17

Slide 17 text

ॏཁͳ΋ͷʁ ॏཁͳ΋ͷ͸ʮϏδωεϧʔϧʯ 17

Slide 18

Slide 18 text

ΫϦʔϯΞʔΩςΫνϟͷਤ 18

Slide 19

Slide 19 text

ॏཁͳ΋ͷʁ ॏཁͳ΋ͷ͸ʮϏδωεϧʔϧʯ • ΤϯςΟςΟ • ࠷ॏཁϏδωεϧʔϧ • Ϣʔεέʔε • ΞϓϦέʔγϣϯݻ༗ͷϏδωεϧʔϧ 19

Slide 20

Slide 20 text

ίΞͱͳΔߟ͑ํ ʮॏཁͳ΋ͷʯΛʮࠣࡉͳ΋ͷʯʹґଘͤ͞ͳ͍ 20

Slide 21

Slide 21 text

ίΞͱͳΔߟ͑ํ ʮॏཁͳ΋ͷʯΛʮࠣࡉͳ΋ͷʯʹґଘͤ͞ͳ͍ 21 ɹɹ ↑ Ͳ͏΍ͬͯʁ

Slide 22

Slide 22 text

ґଘؔ܎ٯస 22

Slide 23

Slide 23 text

యܕతͳґଘؔ܎ͷίʔυ package foo; import bar; class Foo { bar.Bar x; function doFoo() { x.process(); } } 23 package bar; class Bar { function process() { // do something... } }

Slide 24

Slide 24 text

యܕతͳґଘؔ܎ͷίʔυ package foo; import bar; class Foo { bar.Bar x; function doFoo() { x.process(); } } 24 package bar; class Bar { function process() { // do something... } } foo ͔Β bar ͷॲཧΛݺͼग़͢ = ॲཧͷํ޲ foo → bar

Slide 25

Slide 25 text

యܕతͳґଘؔ܎ͷίʔυ package foo; import bar; class Foo { bar.Bar x; function doFoo() { x.process(); } } 25 package bar; class Bar { function process() { // do something... } } foo ͕ bar ͷ͜ͱΛ஌͍ͬͯΔ = ґଘͷํ޲ foo → bar

Slide 26

Slide 26 text

యܕతͳґଘؔ܎ͷίʔυ package foo; import bar; class Foo { bar.Bar x; function doFoo() { x.process(); } } 26 package bar; class Bar { function process() { // do something... } } ॲཧͷํ޲ foo → bar ґଘͷํ޲ foo → bar

Slide 27

Slide 27 text

ґଘؔ܎ٯసͨ͠ίʔυ package foo; class Foo { Buz x; function doFoo() { x.process(); } } interface Buz { function process(); } 27 package bar; import foo; class Bar implements foo.Buz { function process() { // do something... } }

Slide 28

Slide 28 text

ґଘؔ܎ٯసͨ͠ίʔυ package foo; class Foo { Buz x; function doFoo() { x.process(); } } interface Buz { function process(); } 28 package bar; import foo; class Bar implements foo.Buz { function process() { // do something... } }

Slide 29

Slide 29 text

ґଘؔ܎ٯసͨ͠ίʔυ package foo; class Foo { Buz x; function doFoo() { x.process(); } } interface Buz { function process(); } 29 package bar; import foo; class Bar implements foo.Buz { function process() { // do something... } } foo ͔Β bar ͷॲཧΛݺͼग़͢ = ॲཧͷํ޲ foo → bar

Slide 30

Slide 30 text

ґଘؔ܎ٯసͨ͠ίʔυ package foo; class Foo { Buz x; function doFoo() { x.process(); } } interface Buz { function process(); } 30 package bar; import foo; class Bar implements foo.Buz { function process() { // do something... } } bar ͕ foo ͷ͜ͱΛ஌͍ͬͯΔ = ґଘͷํ޲ foo ← bar

Slide 31

Slide 31 text

ґଘؔ܎ٯసͨ͠ίʔυ package foo; class Foo { Buz x; function doFoo() { x.process(); } } interface Buz { function process(); } 31 package bar; import foo; class Bar implements foo.Buz { function process() { // do something... } } ॲཧͷํ޲ foo → bar ґଘͷํ޲ foo ← bar

Slide 32

Slide 32 text

“ιϑτ΢ΣΞΞʔΩςΫτ͸ɺ
 γεςϜʹ͋Δ͢΂ͯͷιʔείʔυͷ
 ґଘؔ܎ͷํ޲Λઈରతʹ੍ޚͰ͖Δ” 32

Slide 33

Slide 33 text

Կ͕خ͍͠ͷ͔ʁ • Ұൠ࿦ͱͯ͠ɺԿ͔Λมߋͨ͠ͱ͖
 ͦΕʹґଘ͍ͯ͠Δ΋ͷશͯʹӨڹ͕ٴͿ ➡ มߋ͞Εʹ͍͘΋ͷʹґଘ͢ΔΑ͏ʹ
 ઃܭ͢Δ͜ͱͰӨڹΛখ͘͞ཹΊΒΕΔ 33

Slide 34

Slide 34 text

ίΞͱͳΔߟ͑ํ ʮॏཁͳ΋ͷʯΛʮࠣࡉͳ΋ͷʯʹґଘͤ͞ͳ͍ 34 σʔλϕʔεɾ UIɾϑϨʔϜϫʔΫͳͲ ༰қʹมߋͰ͖Δ Ϗδωεϧʔϧ มߋ͕ى͜Γʹ͍͘

Slide 35

Slide 35 text

໨࣍ • ͜ͷτʔΫͷΊ͟͢ͱ͜Ζʢ2 ෼ʣ • ΫϦʔϯΞʔΩςΫνϟͷ֓ཁʢ3 ෼ʣ • ίΞͱͳΔߟ͑ํʢ5 ෼ʣ • ۩ମతͳίʔυྫʢ10 ෼ʣ • ·ͱΊʢ3 ෼ʣ • ࣗݾ঺հʢ2 ෼ʣ 35

Slide 36

Slide 36 text

CleanArchitecture ΋͏ͻͱͭͷਤ ग़యɿʰClean Architecture ୡਓʹֶͿιϑτ΢ΣΞͷߏ଄ͱઃܭʱ ʢKindle ൛ɺ ҐஔNo. 3228/6016ʣ 36

Slide 37

Slide 37 text

αϯϓϧɿλεΫ؅ཧπʔϧ • ԼهϦϙδτϦͰ։ൃத • https://github.com/okashoi/laravel-clean- architecture • ͋͘·ͰʮҰྫʯͰ͋Δ͜ͱʹཹҙ • ͜ͷܗ͕ઈରతͳ౴͑Ͱ͸ͳ͍ 37

Slide 38

Slide 38 text

ΤϯςΟςΟ 38

Slide 39

Slide 39 text

·ͣ͸ϏδωεϧʔϧΛநग़ • ʮ࢖͍ํʯʹґΒͳ͍ϧʔϧΛݟग़͢ • ػೳҰཡͰ͸ͳ͍ ʮλεΫΛ࡞੒Ͱ͖ΔʯʮλεΫ໊ΛมߋͰ͖Δʯ ʮλεΫ͸ඞͣλεΫIDͱλεΫ໊Λ࣋ͭʯ
 ɹʮணख೔ʹաڈͷ೔෇ΛೳಈతʹઃఆͰ͖ͳ͍ʯ 39

Slide 40

Slide 40 text

ࣗવݴޠʹىͯ͜͠ readme ʹॻ͍ͨ 40

Slide 41

Slide 41 text

ΤϯςΟςΟͷ࣮૷ • நग़ͨ͠ϏδωεϧʔϧΛ࣮૷Ͱදݱ͢Δ • ϑϨʔϜϫʔΫ΍σʔλϕʔε౳ʹґଘͤ͞ͳ͍ • POPOʢPlain Old PHP ObjectʣͰॻ͘ ➡ ґଘ͢Δ΋ͷ͕ແ͍ͷͰಠཱͯ͠։ൃՄೳ 41

Slide 42

Slide 42 text

ϑϨʔϜϫʔΫʹґଘͤ͞ͳ͍ • ґଘͤ͞Δͷ͸ PHP ૊ΈࠐΈͷΫϥεఔ౓ 42

Slide 43

Slide 43 text

Ϣχοτςετ • ґଘͷແ͍७ਮͳϩδοΫͳͷͰॻ͖΍͍͢ • நग़ͨ͠Ϗδωεϧʔϧͷจݴ͕ͦͷ··ς ετέʔεʹͳΔ 43 /** * @test * @expectedException \MyApp\Components\Tasks\Entities\EstimatedTimeNotSet */ public function 「Inbox」に対して「見積もり時間」が未設定のまま「着手日」を設定できないこと() { $id = Mockery::mock(Id::class); $name = new Name('test'); $inbox = new Inbox($id, $name); $startDate = new StartDate(new DateTimeImmutable('tomorrow')); $inbox->convertToScheduled($startDate); }

Slide 44

Slide 44 text

Ϣʔεέʔε 44

Slide 45

Slide 45 text

Ϣʔεέʔε 45

Slide 46

Slide 46 text

Ϣʔεέʔεͷ࣮૷ • ΞϓϦέʔγϣϯݻ༗ͷϏδωεϧʔϧ • ೖग़ྗͱΤϯςΟςΟΛഔհ͢Δ
 ʮૢ࡞ʯͷΠϝʔδ • ೖग़ྗͷσʔλ͸ഔମ΍σʔλϕʔεʹ
 ґଘ͠ͳ͍ܗʹ͢Δ 46

Slide 47

Slide 47 text

InputBoundary / OutputBoundary • ೖྗʢग़ྗʣσʔλΛҾ਺ʹऔΔ
 ݺͼग़͠ՄೳͳΠϯλʔϑΣʔε 47

Slide 48

Slide 48 text

InputBoundary / OutputBoundary • ೖྗʢग़ྗʣσʔλΛҾ਺ʹऔΔ
 ݺͼग़͠ՄೳͳΠϯλʔϑΣʔε 48

Slide 49

Slide 49 text

Interactor 49 idProvider = $idProvider; $this->taskRepository = $taskRepository; $this->normalOutputBoundary = $normalOutputBoundary; } /** * @param InputData $input */ public function __invoke(InputData $input): void { $inbox = $this->produceEntity($input); $this->taskRepository->save($inbox); $normalOutput = $this->produceNormalOutputData($inbox); ($this->normalOutputBoundary)($normalOutput); } /** * @param InputData $input * @return Task

Slide 50

Slide 50 text

Interactor 50 idProvider = $idProvider; $this->taskRepository = $taskRepository; $this->normalOutputBoundary = $normalOutputBoundary; } /** * @param InputData $input */ public function __invoke(InputData $input): void { $inbox = $this->produceEntity($input); $this->taskRepository->save($inbox); $normalOutput = $this->produceNormalOutputData($inbox); ($this->normalOutputBoundary)($normalOutput); } /** * @param InputData $input * @return Task InputBoundary ͷ࣮૷

Slide 51

Slide 51 text

Interactor 51 idProvider = $idProvider; $this->taskRepository = $taskRepository; $this->normalOutputBoundary = $normalOutputBoundary; } /** * @param InputData $input */ public function __invoke(InputData $input): void { $inbox = $this->produceEntity($input); $this->taskRepository->save($inbox); $normalOutput = $this->produceNormalOutputData($inbox); ($this->normalOutputBoundary)($normalOutput); } /** * @param InputData $input * @return Task ґଘੑ͸֎෦͔Β஫ೖʢDIʣ ※ґଘͯ͠Δ΋ͷΛϞοΫԽͯ͠
 ɹςετ͕ॻ͖΍͍͢

Slide 52

Slide 52 text

Interactor 52 idProvider = $idProvider; $this->taskRepository = $taskRepository; $this->normalOutputBoundary = $normalOutputBoundary; } /** * @param InputData $input */ public function __invoke(InputData $input): void { $inbox = $this->produceEntity($input); $this->taskRepository->save($inbox); $normalOutput = $this->produceNormalOutputData($inbox); ($this->normalOutputBoundary)($normalOutput); } /** * @param InputData $input * @return Task ॲཧຊମ
 ʢ࣍εϥΠυʹղઆଓ͘ʣ

Slide 53

Slide 53 text

Interactor::__invoke() ೖྗσʔλ͔Β
 λεΫΛੜ੒ 53 /** * @param InputData $input */ public function __invoke(InputData $input): void { $inbox = $this->produceEntity($input); $this->taskRepository->save($inbox); $normalOutput = $this->produceNormalOutputData($inbox); ($this->normalOutputBoundary)($normalOutput); }

Slide 54

Slide 54 text

Interactor::__invoke() ੜ੒ͨ͠λεΫΛ
 ӬଓԽ 54 /** * @param InputData $input */ public function __invoke(InputData $input): void { $inbox = $this->produceEntity($input); $this->taskRepository->save($inbox); $normalOutput = $this->produceNormalOutputData($inbox); ($this->normalOutputBoundary)($normalOutput); }

Slide 55

Slide 55 text

Interactor::__invoke() ॲཧ݁Ռ͔Β
 ग़ྗσʔλΛੜ੒ 55 /** * @param InputData $input */ public function __invoke(InputData $input): void { $inbox = $this->produceEntity($input); $this->taskRepository->save($inbox); $normalOutput = $this->produceNormalOutputData($inbox); ($this->normalOutputBoundary)($normalOutput); }

Slide 56

Slide 56 text

Interactor::__invoke() OutputBoundary Λ
 ݺͼग़͠ 56 /** * @param InputData $input */ public function __invoke(InputData $input): void { $inbox = $this->produceEntity($input); $this->taskRepository->save($inbox); $normalOutput = $this->produceNormalOutputData($inbox); ($this->normalOutputBoundary)($normalOutput); }

Slide 57

Slide 57 text

σʔλϕʔε 57

Slide 58

Slide 58 text

σʔλϕʔε • ϢʔεέʔεͰఆٛͨ͠ΠϯλʔϑΣʔεΛ࣮૷ • Repository ύλʔϯΛ࢖͏ͷΛΑ͘ݟΔ • ͜ͷ͋ͨΓ͸ϑϨʔϜϫʔΫʹґଘͤͯ͞΋🙆 • Eloquent Λ࢖͏ͳΒ͜͜Ͱ࢖͏ 58

Slide 59

Slide 59 text

WebʗUI 59

Slide 60

Slide 60 text

WebʗUI • ϢʔεέʔεͰఆٛͨ͠ΠϯλʔϑΣʔεΛ࣮૷ • ਤʹ஧࣮ʹ΍ΔͳΒ Controller ϝιουͷ
 ໭Γ஋͸ void • ͕ɺ͜ͷܗʹ͸ͦ͜·Ͱͩ͜ΘΒͳͯ͘Α͍
 ʢมଇతͳΧελϚΠζ͕ඞཁʹͳΔʣ 60

Slide 61

Slide 61 text

Controller 61 validate($request, [ 'name' => 'required|string|max:255', 'note' => 'string|nullable', ]); $input = new InputData($validated['name'], $validated['note'] ?? ''); $interactor($input); } }

Slide 62

Slide 62 text

Controller 62 validate($request, [ 'name' => 'required|string|max:255', 'note' => 'string|nullable', ]); $input = new InputData($validated['name'], $validated['note'] ?? ''); $interactor($input); } } Laravel ͷ Http\Controllers ͱಉ͡Α͏ʹॻ͚Δ

Slide 63

Slide 63 text

Controller 63 validate($request, [ 'name' => 'required|string|max:255', 'note' => 'string|nullable', ]); $input = new InputData($validated['name'], $validated['note'] ?? ''); $interactor($input); } } HTTPϦΫΤετˠ७ਮͳೖྗσʔλʹม׵

Slide 64

Slide 64 text

Controller 64 validate($request, [ 'name' => 'required|string|max:255', 'note' => 'string|nullable', ]); $input = new InputData($validated['name'], $validated['note'] ?? ''); $interactor($input); } } InputBoundaryʢ࣮ମ͸ InteractorʣΛݺͼग़͢

Slide 65

Slide 65 text

Controller 65 validate($request, [ 'name' => 'required|string|max:255', 'note' => 'string|nullable', ]); $input = new InputData($validated['name'], $validated['note'] ?? ''); $interactor($input); } }

Slide 66

Slide 66 text

Presenter • આ໌ 66 taskId(), $output->taskName(), $output->taskNote(), ); $this->respond($this->view->make('web::tasks.create', compact(['viewModel']))); } }

Slide 67

Slide 67 text

Presenter • આ໌ 67 taskId(), $output->taskName(), $output->taskNote(), ); $this->respond($this->view->make('web::tasks.create', compact(['viewModel']))); } } Interactor Ͱੜ੒͞Εͨग़ྗσʔλΛ ViewModel ʹม׵

Slide 68

Slide 68 text

Presenter • આ໌ 68 taskId(), $output->taskName(), $output->taskNote(), ); $this->respond($this->view->make('web::tasks.create', compact(['viewModel']))); } } View Λੜ੒ͯ͠ϨεϙϯεΛฦ͢ ※มͳ͜ͱ΍ͬͯΔͷ͸ Controllerͷ໭Γ஋Λ
 void ʹ͢ΔͨΊͳͷͰؾʹ͠ͳ͍Ͱ……🙇

Slide 69

Slide 69 text

࢓্͛ • ΠϯλʔϑΣʔεͱ࣮૷ͷΫϥεΛ݁ͼ͚ͭΔ • ServiceProvider Ͱ΍Δ 69

Slide 70

Slide 70 text

70 app->bind(IdProvider::class, AutoIncrementTaskIdProvider::class); $this->app->bind(TaskRepositoryInterface::class, TaskRepository::class); $this->app->bind(InputBoundary::class, Interactor::class); $this->app->bind(NormalOutputBoundary::class, Presenter::class); } /** * Bootstrap any application services. * * @return void */ public function boot() { // } }

Slide 71

Slide 71 text

Laravel ͱͷ෇͖߹͍ํ • Laravel ͷػೳΛ࢖͏ͳΒ֎ଆͷ૚Ͱ࢖͏ • ڧྗͳ DI ͷ࢓૊Έʹ৐͔ͬΔʢServiceContainerʣ • ύοέʔδʹ෼͚ͯ։ൃͯ͠
 ServiceProvider ͰͦΕΒΛ౷߹͢Δ • ී௨ʹॻ͘Ҏ্ʹґଘؔ܎Λҙࣝ͢ΔͷͰ
 ૬ੑ͕͍͍ؾ͕͍ͯ͠Δ 71

Slide 72

Slide 72 text

ࢀߟεϥΠυ@Laravel JP Conference 2019 https://speakerdeck.com/mikakane/laravel-package- development 72

Slide 73

Slide 73 text

σΟϨΫτϦߏ੒ 73

Slide 74

Slide 74 text

σΟϨΫτϦߏ੒ 74 packages ҎԼʹ
 ύοέʔδΛ࡞ͬͯΏ͘

Slide 75

Slide 75 text

σΟϨΫτϦߏ੒ 75 ؔ৺ࣄ୯ҐͰσΟϨΫτϦΛ੾Γ
 ϏδωεϧʔϧΛ࣮૷

Slide 76

Slide 76 text

σΟϨΫτϦߏ੒ 76 σʔλͷѻ͏ॲཧ͚ͩͰͳ͘
 ϚΠάϨʔγϣϯ΋
 ಉҰͷύοέʔδʹೖΕΔ

Slide 77

Slide 77 text

σΟϨΫτϦߏ੒ 77 web ͱ͍͏ׅΓͰ routes ΍
 views ΋ಉҰύοέʔδʹ

Slide 78

Slide 78 text

໨࣍ • ͜ͷτʔΫͷΊ͟͢ͱ͜Ζʢ2 ෼ʣ • ΫϦʔϯΞʔΩςΫνϟͷ֓ཁʢ3 ෼ʣ • ίΞͱͳΔߟ͑ํʢ5 ෼ʣ • ۩ମతͳίʔυྫʢ10 ෼ʣ • ·ͱΊʢ3 ෼ʣ • ࣗݾ঺հʢ2 ෼ʣ 78

Slide 79

Slide 79 text

ίΞͱͳΔߟ͑ํ ʮॏཁͳ΋ͷʯΛʮࠣࡉͳ΋ͷʯʹґଘͤ͞ͳ͍ 79 σʔλϕʔεɾ UIɾϑϨʔϜϫʔΫͳͲ ༰қʹมߋͰ͖Δ Ϗδωεϧʔϧ มߋ͕ى͜Γʹ͍͘

Slide 80

Slide 80 text

ґଘؔ܎ٯసͨ͠ίʔυ package foo; class Foo { Buz x; function doFoo() { x.process(); } } interface Buz { function process(); } 80 package bar; import foo; class Bar implements foo.Buz { function process() { // do something... } }

Slide 81

Slide 81 text

͜ͷτʔΫͷΊ͟͢ͱ͜Ζ🏁 • ΫϦʔϯΞʔΩςΫνϟͷίΞͱͳΔߟ͑ํ • ͦΕΛ࣮ݱ͢ΔͨΊͷ۩ମతͳίʔσΟϯά • ͦΕΒΛ࣮ફ͢Δ্Ͱͷ Laravel ͱͷ෇͖߹͍ํ ͜ΕΒΛ஌ͬͯ΋Β͍ɺͦͷҰ෦෼͚ͩͰ΋
 ͜Ε͔Βͷ։ൃʹ׆͔ͯ͠΋Β͏ 81

Slide 82

Slide 82 text

໨࣍ • ͜ͷτʔΫͷΊ͟͢ͱ͜Ζʢ2 ෼ʣ • ΫϦʔϯΞʔΩςΫνϟͷ֓ཁʢ3 ෼ʣ • ίΞͱͳΔߟ͑ํʢ5 ෼ʣ • ۩ମతͳίʔυྫʢ10 ෼ʣ • ·ͱΊʢ3 ෼ʣ • ࣗݾ঺հʢ2 ෼ʣ 82

Slide 83

Slide 83 text

ࣗݾ঺հ Ԭా ਖ਼ฏ / ͓͔͠ΐ͍ @okashoi @okashoi ΞʔΩςΫτ ݉ ٕज़޿ใ 83

Slide 84

Slide 84 text

ࣗݾ঺հ ίϛϡχςΟ׆ಈ • Hacker’s GATE ӡӦ 84

Slide 85

Slide 85 text

ࣗݾ঺հ ίϛϡχςΟ׆ಈ • एख΋ͷͮ͘Γूஂ Oysters ϝϯόʔ 85

Slide 86

Slide 86 text

ࣗݾ঺հ ίϛϡχςΟ׆ಈ • Laravel JP Conference 2020 ίΞελοϑ 86 https://conference2020.laravel.jp/

Slide 87

Slide 87 text

ࣗݾ঺հ Ask the Speaker ΍ ࠙਌ձͰ
 ͓࿩͕Ͱ͖ͨΒخ͍͠Ͱ͢ 😂 87