KEMBAR78
クリーンアーキテクチャの考え方にもとづく Laravel との付き合い方 #phpconokinawa | PDF
Laravel
PHP Conference Okinawa 2019
@okashoi WILLGATE, Inc.
•
• 🙆
•
• #phpconokinawa
2


※ 2019/09/21 

PHP 2019 

3
• 2
• 3
• 5
• Laravel 10
• 3
• 2
4
• 2
• 3
• 5
• Laravel 10
• 3
• 2
5
• 2
• 3
• 5
• Laravel 10
• 3
• 2
6
• 2
• 3
• 5
• Laravel 10
• 3
• 2
7
• 2
• 3
• 5
• Laravel 10
• 3
• 2
8
• 2
• 3
• 5
• Laravel 10
• 3
• 2
9
🏁
•
• Laravel
10
🙅
•
• Laravel
•
11
• 2
• 3
• 5
• Laravel 10
• 3
• 2
12
2012
”The Clean Architecture - The Clean Code Blog”,
https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html
13
14
2017 2018
”The Clean Architecture - The Clean Code Blog”,
https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html
15
• 

•
•
16
•
•
•
※ PHP
17
“ 

”
18
• 2
• 3
• 5
• Laravel 10
• 3
• 2
19
20
21
22
🙅
23
24
• Enterprise Business Rules
•
•
• Application Business Rules
•
25
https://little-hands.hatenablog.com/entry/2019/07/26/
domain-knowledge 26
27
28
↑
29
package foo;
import bar;
class Foo {
bar.Bar x;
function doFoo() {
x.process();
}
}
30
package bar;
class Bar {
function process() {
// do something...
}
}
package foo;
import bar;
class Foo {
bar.Bar x;
function doFoo() {
x.process();
}
}
31
package bar;
class Bar {
function process() {
// do something...
}
}
foo bar = foo → bar
package foo;
import bar;
class Foo {
bar.Bar x;
function doFoo() {
x.process();
}
}
32
package bar;
class Bar {
function process() {
// do something...
}
}
foo bar = foo → bar
package foo;
import bar;
class Foo {
bar.Bar x;
function doFoo() {
x.process();
}
}
33
package bar;
class Bar {
function process() {
// do something...
}
}
foo → bar
foo → bar
package foo;
class Foo {
Buz x;
function doFoo() {
x.process();
}
}
interface Buz {
function process();
}
34
package bar;
import foo;
class Bar implements foo.Buz {
function process() {
// do something...
}
}
package foo;
class Foo {
Buz x;
function doFoo() {
x.process();
}
}
interface Buz {
function process();
}
35
package bar;
import foo;
class Bar implements foo.Buz {
function process() {
// do something...
}
}
package foo;
class Foo {
Buz x;
function doFoo() {
x.process();
}
}
interface Buz {
function process();
}
36
package bar;
import foo;
class Bar implements foo.Buz {
function process() {
// do something...
}
}
foo bar = foo → bar
package foo;
class Foo {
Buz x;
function doFoo() {
x.process();
}
}
interface Buz {
function process();
}
37
package bar;
import foo;
class Bar implements foo.Buz {
function process() {
// do something...
}
}
bar foo = foo ← bar
package foo;
class Foo {
Buz x;
function doFoo() {
x.process();
}
}
interface Buz {
function process();
}
38
package bar;
import foo;
class Bar implements foo.Buz {
function process() {
// do something...
}
}
foo → bar
foo ← bar
=
39
“ 



”
40
• 

➡ 

41
42
UI
• 2
• 3
• 5
• Laravel 10
• 3
• 2
43
Laravel
• DI
• Eloquent
44
Laravel
• 

Service Provider
• Laravel 

45
Laravel
• 

Service Provider
• Laravel 

46
@Laravel JP Conference 2019
https://speakerdeck.com/mikakane/laravel-package-
development 47
48
packages 

Service Provider
•
• 

• =
• =
49
Service Provider
50
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* @return void
*/
public function register()
{
$this->app->bind(IdProvider::class, AutoIncrementTaskIdProvider::class);
$this->app->bind(TaskRepositoryInterface::class, TaskRepository::class);
}
Service Container


51
/**
* Interactor constructor.
* @param IdProvider $idProvider
* @param TaskRepository $taskRepository
* @param NormalOutputBoundary $normalOutputBoundary
*/
public function __construct(IdProvider $idProvider, TaskRepository $taskRepository, …
{
$this->idProvider = $idProvider;
$this->taskRepository = $taskRepository;
$this->normalOutputBoundary = $normalOutputBoundary;
}
Laravel
• 

Service Provider
• Laravel 

52
Clean Architecture
Clean Architecture
Kindle No. 3228/6016 53
54
55
•
•
TODO
ID 

56
•
•
• POPO Plain Old PHP Object
➡
57
PHP
58
<?php
namespace MyAppEntitiesTask;
use DatetimeImmutable;
/**
* Class Inbox
* @package MyAppEntitiesTask
*/
final class Inbox extends Task
{
/**
* @var EstimatedTime|null
*/
private $estimatedTime;
59
60
•
• 

• 

61
62
<?php
namespace MyAppComponentsCreateInboxUseCase;
use MyAppEntitiesTask{Task, Id};
/**
* Interface TaskRepository
* @package MyAppComponentsCreateInboxUseCase
*/
interface TaskRepository
{
/**
* 与えられたタスクを永続化する
*
* @param Task $task
*/
public function save(Task $task): void;
63
Web UI
64
Web UI
65
Web UI
•
• 🙆
• Eloquent
66
<?php
namespace MyAppComponentsCreateInboxDataAccessDatabaseRepositories;
// 略
/**
* Class TaskRepository
* @package MyAppComponentsCreateInboxDataAccessDatabaseRepositories
*/
class TaskRepository implements TaskRepositoryInterface
{
/**
* 与えられたタスクを永続化する
*
* @param Task $task
*/
public function save(Task $task): void
{
$taskRecord = EloquentsTask::create([
'name' => $task->name()->value(),
'note' => $task->note()->value(),
]);
67
<?php
namespace MyAppComponentsCreateInboxDataAccessDatabaseRepositories;
// 略
/**
* Class TaskRepository
* @package MyAppComponentsCreateInboxDataAccessDatabaseRepositories
*/
class TaskRepository implements TaskRepositoryInterface
{
/**
* 与えられたタスクを永続化する
*
* @param Task $task
*/
public function save(Task $task): void
{
$taskRecord = EloquentsTask::create([
'name' => $task->name()->value(),
'note' => $task->note()->value(),
]);
Eloquent
68
“ 







”
69
WIP
https://github.com/okashoi/laravel-clean-
architecture
•
•
•
70
• 2
• 3
• 5
• Laravel 10
• 3
• 2
71
72
UI
package foo;
class Foo {
Buz x;
function doFoo() {
x.process();
}
}
interface Buz {
function process();
}
73
package bar;
import foo;
class Bar implements foo.Buz {
function process() {
// do something...
}
}
Laravel
• 

Service Provider
• Laravel 

74
• 2
• 3
• 5
• 10
• 3
• 2
75
/
@okashoi
@okashoi
76
• Hacker’s GATE
77
• Oysters
78
• Laravel.shibuya
79
• Laravel Shibuya Radio
80
• Laravel JP Conference 2020
81https://conference2020.laravel.jp/
/
@okashoi
@okashoi
82
😄

クリーンアーキテクチャの考え方にもとづく Laravel との付き合い方 #phpconokinawa