Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Laravelを始めて DDDを実践するまで
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Kazuki Ohashi
March 08, 2018
Technology
2k
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Laravelを始めて DDDを実践するまで
Laravelを始めてから、DDDを実践するまでの過程
Kazuki Ohashi
March 08, 2018
More Decks by Kazuki Ohashi
See All by Kazuki Ohashi
larave_vue_graphql_supplementation
kzkohashi
1
910
Introduction to using GraphQL for a bit
kzkohashi
0
270
フォロワーがどの雑誌に興味があるのか可視化してみる / magazine-score
kzkohashi
0
760
Amazon Rekognitionを用いてフォロワーの男女比を出す
kzkohashi
1
3k
Other Decks in Technology
See All in Technology
なぜ東京にいる私が、新潟の技術コミュニティを運営するのか by 八雲慎之助
yakumo
0
220
`go get`したらELFが降ってきた件
taiyow
0
190
[JAWS Festa 2026]一番いい仕事は、請求書に現れない / jawsfesta2026
sh_fk2
2
340
AWSを利用する上で知っておきたい名前解決の話 2026
nagisa53
5
3.2k
IBC 2026 動画技術関連レポート / IBC 2026 Report
cyberagentdevelopers
PRO
2
440
試験勉強はGrokBotでやれ
maigo999
0
110
Kiro Crew の Bot (続く役目を任せる窓口) | 目指せ Kiro マスター 12
inariku
PRO
2
290
2026 Apache Flink Community Checkpoint
rmetzger
0
200
Claude Codeで作ったアプリを安全に公開する/Built with Claude Japan 2026
yoshidashingo
0
200
レガシーコードに対する loop engineering的なAI開発プロセス導入について
kubell_hr
0
280
AI AgentによるEmbedded SREの取り組み
tgidgd
1
360
現場を動かすAIエージェント#2_製造業現場でのAI活用から見た、ハマる罠と実践知
kintotechdev
2
190
Featured
See All Featured
A designer walks into a library…
pauljervisheath
211
25k
Optimizing for Happiness
mojombo
378
71k
Rebuilding a faster, lazier Slack
samanthasiow
85
9.7k
Between Models and Reality
mayunak
4
560
Navigating Weather and Climate Data
rabernat
0
590
コードの90%をAIが書く世界で何が待っているのか / What awaits us in a world where 90% of the code is written by AI
rkaga
63
48k
Design of three-dimensional binary manipulators for pick-and-place task avoiding obstacles (IECON2024)
konakalab
0
650
JAMstack: Web Apps at Ludicrous Speed - All Things Open 2022
reverentgeek
1
670
Typedesign – Prime Four
hannesfritz
42
3.2k
So, you think you're a good person
axbom
PRO
2
2.3k
Designing Experiences People Love
moore
143
24k
Imperfection Machines: The Place of Print at Facebook
scottboms
270
14k
Transcript
-BSBWFMΛ࢝Ίͯ %%%Λ࣮ફ͢Δ·Ͱ Laravel Meetup Tokyo Vol.10 େڮ Ұथ @kzkohashi
େڮҰथ!L[LPIBTIJ w ΠϯϑϧΤϯαʔϚʔέςΟϯά w αʔόαΠυ ϑϩϯτத৺ w -BSBWFM࢝Ίͯ̍͘Β͍ w %%%ษڧ࢝͠Ίͯϲ݄
%%%ͬͯΔ PS %%%࣮ફͯ͠Δํ
ࠓ͓͢͠Δ͜ͱ -BSBWFMͰ%%%Λ࣮ફ͢Δ·Ͱͷաఔ %%%Λ࣮ફ͢Δ͜ͱͰԿ͕มΘͬͨʁ ٯʹฉ͍ͯΈ͍ͨ
-BSBWFM࢝ΊΔ
͍͍ɻΊͪΌ͍͍ɻ w ͙͢ʹؾ࣋ͪΑ͔͚͘Δ w ཉ͍͠ػೳ͕σϑΥϧτͰ͋Δʢ֦ு͍͢͠ʂʂ w ϥΠϒϥϦ๛ w ຊޠॆ࣮
ॻ͖͍͢ɺઃܭΛ͔ͬ͠Γ͠ͱ͖͍ͨ
%%%Λษڧ࢝͠ΊΔ
͍͍ɻΊͪΌ͍͍ɻ w ݱ࣮ͷؔ৺ΛͰ͖Δ͚ͩ։ൃ্ͱͰγϯΫϩͤ͞Δ w υϝΠϯΤΩεύʔτͱΤϯδχΞͷҰॹʹ͠߹ͬͯϞ σϦϯά͍ͯ͘͠ w ڞ௨ݴޠʢϢϏΩλεݴޠʣͷൃ۷ w ͳΜͲมߋɾվળ͍ͯ͘͠ͷ
֓೦ૉΒ͍͠ʂ
Ͱɺ࣮ફํ๏ʁ
࣮ફͷෑډߴ͍ʁ w ຊಡΉ͚ͩ͡ΌΑ͘Θ͔Βͳ͍ w ࣮ફͯ͠ͳ͕Βͬͯͨ΄͏͕Αͦ͞͏ w 8FCʹ࣮ફ͢ΔͨΊͷ৭ʑͳΞʔΩςΫνϟͳͲ͕͋Δ ௐͨͱ͖ʹΑ͘࠾༻͞Ε͍ͯΔ 3FQPTJUPSZύλʔϯΛಋೖ
$POUSPMMFS 4FSWJDF 3FQPTJUPSZ &MPRVFOU3FQPTJUPSZ .PEFM ϓϨθϯςʔγϣϯ ϏδωεϩδοΫ σʔλૢ࡞ ϏδωεϩδοΫ͔Βσʔλૢ࡞ͷॲཧΛΓ͢ ʢ˞ඞͣͦ͠͏Ͱͳ͍ʣ
ͱ͋ΔαʔϏεͷྫ Ϣʔεέʔε w ϝʔΧʔΞΧϯτΛొ͢Δ w ϝʔΧʔΞΧϯτΛෳ࡞ΕΔ Ϟσϧ
interface MakerAccountRepository { public function getLoginAccountByEmail($email); public function findById($id); public
function register($name, $tel, $email, $password); } 3FQPTJUPSZ ར༻͢ΔࡍͷΠϯλʔϑΣʔε
class EloquentMakerAccountRepository implements MakerAccountRepository { /** @var \App\Models\MakerAccount */ protected
$maker_account; public function __construct(MakerAccount $maker_account) { $this->maker_account = $maker_account; } public function getLoginUserByEmail($email) { return $this->maker_account->whereEmail($email) ->with('maker') ->first(); } public function register($maker_id, …) { $data[‘…’] = $maker_id; … return $this->maker_account->create($data); } } &MPRVFOU3FQPTJUPSZ .PEFMΛ%*
class MakerAccountRegisterService { protected $maker_repo; protected $maker_account_repo; public function __construct(
MakerRepository $maker_repo, MakerAccountRepository $maker_account_repo ) { $this->maker_repo = $maker_repo; $this->maker_account_repo = $maker_account_repo; } protected function register($maker_name,…লུ) { return \DB::transaction(function () use (...লུ) { /** @var \App\Models\Maker $maker */ $maker = $this->maker_repo->register($maker_name, $address); $this->maker_account_repo->register( $maker->id, $staff_name, $tel, $email, $password ); }); } } 4FSWJDF ϦϙδτϦʔΛ௨ͯ͠ొ
Կ͔มΘͬͨʁ w ϏδωεϩδοΫͱσʔλૢ࡞ΛେମΓͤͨ w ݁ہฦ͍ͯ͠Δͷ͕&MPRVFOUͷͨΊɺ֎ଆͰૢ࡞Մೳ σʔλૢ࡞͕౷Ұ͞ΕͯΔ෩ͳͷ͚͕ͩͰ͖ͨ
େ͖ͳצҧ͍ %%%ઃܭͱ͍͏ͷΛΕͣʹ
ΤϯδχΞ૿͑ͨ ਓਓ ˞ϝΠϯ࣮ऀͷ͕Ͳ͔ͬʹ͍·͢ !BJJSP
ࠓ࣮ͦ͜ફ w Կ͔Β࢝ΊͨΒ͍͍ʁ w όϦϡʔΦϒδΣΫτ͔Β࢝ΊͨΒΓ͍͢ͱຢฉ͖ !BJJSP
όϦϡʔΦϒδΣΫτͱʁ w ϓϦϛςΟϒܕͰදݱ͍ͯͨ͠ΛΦϒδΣΫτʹ͢Δ w ࣗͷՃɾఆͳͲͷৼΔ͍Λ࣋ͭ w ΠϛϡʔλϒϧͰ͋Δ
$POUSPMMFS 4FSWJDF 3FQPTJUPSZ &MPRVFOU3FQPTJUPSZ .PEFM ෦తʹ7BMVF0CKFDUʹม υϝΠϯʁ 7BMVF0CKFDU
ͱ͋ΔαʔϏεͷྫ Ϣʔεέʔε w ϝʔΧʔΞΧϯτΛొ͢Δ w ొ͞Ε͍ͯΔϝʔϧ͕ϒϥοΫϦετͷ߹YYY͢Δ Ϟσϧ &NBJMΛ7BMVF0CKFDUʹͯ͠ΈΔ
class Email implements \JsonSerializable { protected $value; protected function __construct(string
$value) { $this->value = $value; } public function value(): string { return $this->value; } public function isBlackList(): boolean { return ($this->value === $blacklist) } public function jsonSerialize() { return $this->value; } } 7BMVF0CKFDU ৼΔ͍Λ࣋ͨͤΔ
class MakerAccount extends Model { protected $table = 'maker_accounts'; protected
$hidden = [ 'id', ]; public function toValueObject() { // Πϛϡʔλϒϧʹ͢ΔͨΊɺreplicate()ͨ݁͠ՌΛฦ٫ $replication = $this->replicate(); $replication->email = new Email($this->email); return $replication; } } .PEFM ରͷ7BMVF0CKFDUΛ٧ΊࠐΉ
class MakerAccountRegisterService { protected $maker_account_repo; public function __construct(MakerAccountRepository $maker_account_repo) {
$this->maker_account_repo = $maker_account_repo; } public function activateEmail($email) { $maker_account = $this->maker_account_repo->findByEmail($email); $maker_account = $maker_account->toValueObject(); return $maker_account->email->isBlackList(); } } 4FSWJDF 7BMVF0CKFDUͷৼΔ͍Λར༻
ײ w 7BMVF0CKFDUͷΈͩͱखܰʹ࢝ΊΒΕΔ w ৼΔ͍Λू͢Δ͜ͱͰΘ͔Γ͘͢ͳͬͨ গͣͭ͠%%%ͷԸܙ͕ड͚ΒΕ͖ͯͨɾɾʁ
৽نαʔϏεͷ։ൃ
ϑϧͰ%%%ͷ࣮ફ νϟϯεʂ IUUQTHJUIVCDPNTIJOYMBSBWFMEEETBNQMF ৽ݪ͞ΜͷΊͪΌͪ͘Όࢀߟʹͯ͠·͢
ΤϯςΟςΟͱ w ҰҙʹࣝผՄೳͳΦϒδΣΫτ w ෳͷΦϒδΣΫτৼΔ͍Λ͍࣋ͬͯΔ w ৼΔ͍͕গͳ͍߹ݕ౼͖͢
$POUSPMMFS 6TF$BTF 3FQPTJUPSZ &MPRVFOU3FQPTJUPSZ .PEFM υϝΠϯ &OUJUZΛฦ͢ 7BMVF0CKFDU &OUJUZ
ͱ͋ΔαʔϏεͷྫ Ϣʔεέʔε w ը໘͔ΒϝʔΧʔ͕ ࣗͷ ΞΧϯτҰཡӾཡ͢Δ w ϝʔΧʔͷΞΧϯτͷҰཡΛϖʔδωʔγϣϯͰฦ͢ Ϟσϧ ϞσϧΛ&OUJUZʹͯ͠ΈΔ
class MakerAccount implements \Arrayable { /** @var MakerId */ protected
$maker_id; protected $name; protected $tel; protected $email; protected $password; public function __construct(MakerId $maker_id,…লུ) { $this->maker_id = $maker_id; $this->email = $email; if ($password) { $this->password = MakerAccountPassword::of(\Hash::make($password->value())); } } public function toArray() { $array = []; $class_vars = array_keys(get_class_vars(static::class)); foreach ($class_vars as $var_name) { $array[$var_name] = $this->{$var_name}; } return $array; } } &OUJUZ ֤7BMVF0CKFDUΛ٧ΊࠐΉ
class MakerAccount extends Model implements Domainable { public function maker()
{ return $this->belongsTo(Maker::class); } /** * @return \App\Domains\Entities\MakerAccount */ public function toDomain() { return new Entities\MakerAccount( MakerId::of($this->maker_id), MakerAccountName::of($this->name), MakerAccountTel::of($this->tel), MakerAccountEmail::of($this->email) ); } } .PEFM &OUJUZʹม
class DomainServiceProvider extends ServiceProvider { … protected function collectionMacro() {
Builder::macro('toDomainCollection', function () { /** @noinspection PhpUndefinedMethodInspection */ return $this->get()->map(function (Domainable $model) { return $model->toDomain(); }); }); Collection::macro('toDomainCollection', function () { /** @noinspection PhpUndefinedMethodInspection */ return $this->map(function (Domainable $model) { return $model->toDomain(); }); }); } protected function paginateMacro() { … } } $PMMFDUJPO #VJMEFS͔Β%PNBJOͷྻΛฦ͢.BDSPΛՃ
class FetchMakerAccountList { protected $maker_account_repo; public function __construct(MakerAccountRepository $maker_account_repo) {
$this->maker_account_repo = $maker_account_repo; } protected function common(MakerAccountId $maker_account_id) { return $this->maker_account_repo->findByMakerIdAsModel($maker_id); } public function asCollection(MakerId $maker_id) { return $this->common($maker_id)->toDomainCollection(); } public function asPaginate(MakerId $maker_id) { return $this->common($maker_id)->domainPaginate(); } } 6TF$BTF ೋͭͷৼΔ͍Λ࣋ͨͤͯͨ
class MakerAccountController extends Controller { public function index(FetchMakerAccountList $usecase) {
$maker_accounts = $usecase->asPaginate(MakerId::of(auth()->maker->id())); return response()->json($maker_accounts); } } $POUSPMMFS ར༻
6TF$BTFʹෳͷৼΔ͍ͨͤͯ͠·͍ͬͯΔ 6TF$BTFͷमਖ਼
;Ή;Ή 6TF$BTFͷमਖ਼
class FetchMakerAccountPaginate { protected $maker_account_repo; public function __construct(MakerAccountRepository $maker_account_repo) {
$this->maker_account_repo = $maker_account_repo; } public function __invoke(MakerAccountId $maker_account_id) { return $this->maker_account_repo ->findByMakerIdAsModel($maker_id) ->domainPaginate(); } } 6TF$BTFʢमਖ਼ޙʣ ҰͭͷৼΔ͍ͷΈʹ੍ݶ
class MakerAccountController extends Controller { public function index(FetchMakerAccountList $usecase) {
$maker_accounts = $usecase(MakerId::of(auth()->maker->id())); return response()->json($maker_accounts); } } $POUSPMMFS ར༻
ࠓ͓ͨ͜͠ͱ -BSBWFMͰ%%%Λ࣮ફ͢Δ·Ͱͷաఔ %%%Λ࣮ફ͢Δ͜ͱͰԿ͕มΘͬͨʁ ҰͰແཧͰɺগͣͭ͠ͳΒ࣮ફͰ͖Δ ༷ͷѲ͕͘͢͠ͳͬͨ ϏδωεαΠυͱͷೝ͕ࣝͱΓ͘͢ͳͬͨ ઃܭ ࣮ ྑ͍ϧʔϓ
͝੩ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠
ฉ͖͍ͨ͜ͱ w &OUJUZ͕&OUJUZΛ࣋ͭ߹ͷύϑΥʔϚϯεͷ w όϦσʔγϣϯͲ͜Ͱ࣋ͨͤΔ͖͔ w ࣮ࡍͬͯΈͯɺԿ͕ྑ͔ͬͨͷ͔