Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Slim Frameworkで始めるPHPのmiddleware
Search
YAMAOKA Hiroyuki
July 15, 2017
Technology
4
2.3k
Slim Frameworkで始めるPHPのmiddleware
2017年7月17日、PHPカンファレンス関西2017での発表資料です。
https://2017.kphpug.jp/
YAMAOKA Hiroyuki
July 15, 2017
Tweet
Share
More Decks by YAMAOKA Hiroyuki
See All by YAMAOKA Hiroyuki
コードとあなたと私の距離 / The Distance Between Code, You, and I
hiro_y
0
290
エンジニアの「センス」とは何か / What is the sense of engineers
hiro_y
21
9.8k
CSRF対策のやり方、そろそろアップデートしませんか / Update your knowledge of CSRF protection
hiro_y
32
30k
PHPで任意精度演算を行って「正しい」金額計算をする方法 / Perform arbitrary precision arithmetic in PHP to achieve "accurate" monetary calculations
hiro_y
2
3.9k
PHPのバージョンアップ実際のところどうなの? / How actually upgrade of PHP is
hiro_y
3
830
PHPのDI、attributesとこれから / PHP DI with attributes
hiro_y
1
2.6k
PHPのアノテーションの仕組みとメリット・デメリット / About PHP annotations
hiro_y
1
9.4k
株式会社 USEN Media - PHPカンファレンス北海道2019 / 2019-09-21_phpcondo-2019_usen-media
hiro_y
0
310
PHPのmiddlewareを 使いこなすために
hiro_y
4
2.6k
Other Decks in Technology
See All in Technology
たかがボタン、されどボタン ~button要素から深ぼるボタンUIの定義について~ / BuriKaigi 2026
yamanoku
1
290
サラリーマンソフトウェアエンジニアのキャリア
yuheinakasaka
41
19k
ソフトとハード両方いけるデータ人材の育て方
waiwai2111
1
480
Sansan Engineering Unit 紹介資料
sansan33
PRO
1
3.7k
Scrum Guide Expansion Pack が示す現代プロダクト開発への補完的視点
sonjin
0
740
All About Sansan – for New Global Engineers
sansan33
PRO
1
1.3k
善意の活動は、なぜ続かなくなるのか ーふりかえりが"構造を変える判断"になった半年間ー
matsukurou
0
570
Hardware/Software Co-design: Motivations and reflections with respect to security
bcantrill
1
140
田舎で20年スクラム(後編):一個人が企業で長期戦アジャイルに挑む意味
chinmo
1
1.6k
コミュニティが持つ「学びと成長の場」としての作用 / RSGT2026
ama_ch
2
350
迷わない!AI×MCP連携のリファレンスアーキテクチャ完全ガイド
cdataj
0
580
First-Principles-of-Scrum
hiranabe
4
2.3k
Featured
See All Featured
The Spectacular Lies of Maps
axbom
PRO
1
440
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
55
3.2k
Lightning Talk: Beautiful Slides for Beginners
inesmontani
PRO
1
420
Max Prin - Stacking Signals: How International SEO Comes Together (And Falls Apart)
techseoconnect
PRO
0
67
Intergalactic Javascript Robots from Outer Space
tanoku
273
27k
Amusing Abliteration
ianozsvald
0
87
Mozcon NYC 2025: Stop Losing SEO Traffic
samtorres
0
120
WCS-LA-2024
lcolladotor
0
420
The Illustrated Children's Guide to Kubernetes
chrisshort
51
51k
Fireside Chat
paigeccino
41
3.8k
From Legacy to Launchpad: Building Startup-Ready Communities
dugsong
0
130
It's Worth the Effort
3n
188
29k
Transcript
4MJN'SBNFXPSLͰ࢝ΊΔ 1)1ͷNJEEMFXBSF 1)1ΧϯϑΝϨϯεؔ ߹ಉձࣾςϯϚυɹࢁԬ
ࣗݾհ ࢁԬ!IJSP@Z 1)1ͱ͔/PEFKTͱ͔ॻ͖·͢ Ұ൪͖ͳͷ$44 ߹ಉձࣾςϯϚυදࣾһ
߹ಉձࣾςϯϚυ ݄ઃཱʢظʣ දࣾһਓ!! Ϗδωεࢧԉࣄۀ αʔϏε։ൃࣄۀ
JSVDBNJNFNPDPOBTV
NJEEMFXBSFͱʁ ͱ͍͏Λ͠·͢
XFCΞϓϦέʔγϣϯͱ )551ͷϦΫΤετΛड͚औΓ ͍Ζ͍ΖॲཧΛͯ͠ ೝূͱ͔%#ʹσʔλอଘͱ͔ ͍ΘΏΔϏδωεϩδοΫ
)551ͷϨεϙϯεΛฦ͢
؆୯ʹඳ͘ͱ͜͏
ϑΟϧλʔͱ͍͏ൃ શϦΫΤετڞ௨ͷॲཧ ॲཧલͷϩάΠϯೝূ ॲཧલͷσʔλऔಘɹͳͲ ΞϓϦέʔγϣϯຊମͷલʹ ॲཧΛڬΊΔΑ͏ʹ͢ΕΑ͍ͷͰ
ϑΟϧλʔʢલॲཧʣ
ϑΟϧλʔͷൃɺଓ͖ શϦΫΤετڞ௨ͷॲཧɺ·ͩ͋Δ ॲཧޙͷϩΪϯά ॲཧޙʹ·ͱΊͯϝʔϧૹ৴ ΞϓϦέʔγϣϯຊମͷޙʹ ॲཧΛڬΊΔΑ͏ʹ͢Ε͍͍ΑͶ
ϑΟϧλʔʢޙॲཧʣ
͜͜Ͱ/PEFKTͷ &YQSFTTͷΛ͠·͢
&YQSFTT IUUQFYQSFTTKTDPN l'BTU VOPQJOJPOBUFE NJOJNBMJTUXFCGSBNFXPSLGPS /PEFKTz
/PEFKTͰҰ൪ΘΕ͍ͯΔ XFCΞϓϦέʔγϣϯϑϨʔϜϫʔΫ
)FMMP8PSME const express = require('express'); const app = express(); app.get('/',
function(req, res) { res.send('Hello World!'); }); app.listen(3000);
͖ͬ͞ͷਤ
&YQSFTTͷߏ SPVUJOH ϦΫΤετΛॲཧʹϚοϐϯά NJEEMFXBSF SPVUJOHͷաఔͰ ҙͷॲཧΛࠩ͠ࠐΉͨΊͷΈ
&YQSFTTͷNJEEMFXBSF ͍Ͳ͜Ζ ڞ௨ॲཧʢલॲཧɺޙॲཧʣ ͭͷSPVUJOHʹରͯ͠ෳ࿈݁Ͱ͖Δ OFYUDBMMCBDLΛݺͿͱ ࣍ͷNJEEMFXBSFʹॲཧ͕ҠΔ
࣮ߦͷॱংએݴॱ
NJEEMFXBSFͷجຊ function(req, res, next) { // Կ͔લॲཧΛ͢Δ next(); // ࣍ͷmiddlewareΛݺͿ
// Կ͔ޙॲཧΛ͢Δ };
NJEEMFXBSFͷྫ const myLogger = function(req, res, next) { console.log('Logged!'); next();
}; app.get('/', myLogger, function(req, res) { res.send('Hello World!'); });
NJEEMFXBSFͷྫ શ const myLogger = function(req, res, next) { console.log('Logged!');
next(); }; app.use(myLogger); // શϦΫΤετʹద༻ app.get('/', function(req, res) { res.send('Hello World!'); });
ೖΕࢠʹͳ͍ͬͯΔ
NJEEMFXBSFͷྫʢෳʣ const auth = function(req, res, next) {}; const logger
= function(req, res, next) {}; app.get('/', auth, logger, function(req, res) { res.send('Hello World!'); });
NJEEMFXBSFͷྫʢʁʣ const myLogger = function(req, res) { console.log('Logged!'); }; app.get('/',
function(req, res, next) { res.send('Hello World!'); next(); }, myLogger); // ॲཧ࣮ߦޙʹݺΕΔ
͋ΒΏΔॲཧ͕ NJEEMFXBSFͱͯ͠ ࣮ɾ࣮ߦ͞ΕΔੈք
ೖΕࢠঢ়ଶ
λϚωΪΈ͍ͨʁ QIPUPCZEBSXJO#FMMMJDFOTFEVOEFS$$#: IUUQTXXXqJDLSDPNQIPUPTEBSXJOCFMM
Ұํ1)1Ͱ ʢؼ͖ͬͯͨʂʣ
4UBDL1)1 IUUQTUBDLQIQDPN l$PNQPTJOH)UUQ,FSOFM*OUFSGBDF NJEEMFXBSFTTJODFz l8IBUEPXFXBOU 3FVTFBUUIF XFCMBZFSz
4ZNGPOZͷ)UUQ,FSOFM*OUFSGBDF
4UBDL1)1
ͰͦΖͦΖ 4MJN'SBNFXPSLͷ
4MJN'SBNFXPSLW IUUQTXXXTMJNGSBNFXPSLDPN )5513PVUFS .JEEMFXBSF 1434VQQPSU
%FQFOEFODZ*OKFDUJPO
143 IUUQXXXQIQpHPSHQTSQTS )551NFTTBHFJOUFSGBDFT 1TSa)UUQa.FTTBHFa3FRVFTU*OUFSGBDF 1TSa)UUQa.FTTBHFa3FTQPOTF*OUFSGBDF
XFCΞϓϦͷೖग़ྗͷඪ४Խ
)FMMP8PSME // autoloadͱ͔useলུ… $app = new \Slim\App(); $app->get('/', function($request, $response)
{ $response->getBody() ->write('Hello World!'); return $response; }); $app->run();
؆୯Ͱ͠ΐʁ
͍Α͍Α NJEEMFXBSFͷ
NJEEMFXBSFʢؔʣ function(Request $request, Response $response, callable $next): Response { //
Կ͔લॲཧΛ͢Δ $response = $next($request, $response); // Կ͔ޙॲཧΛ͢Δ return $response; };
NJEEMFXBSFʢΫϥεʣ class ExampleMiddleware { public function __invoke( Request $request, Response
$response, callable $next ): Response { // …ؔͷͱ͖ͱಉ͡ } }
NJEEMFXBSFͷద༻ $app->get('/', function($request, $response) { // Կ͔ॲཧͯ͠ResponseΛฦ͢ })->add(ExampleMiddleware::class); // ͠શॲཧʹڬΉͳΒ
$app->add(ExampleMiddleware::class);
DPOUSPMMFS // $app->get('/', ExampleAction::class); class ExampleAction { public function __invoke(
Request $request, Response $response, array $args): Response { return $response; } }
%*ίϯςφͱ Έ߹ΘͤΔͱ ͬͱศརʹ
4MJNͷ%*ίϯςφͷҐஔ͚ Πϯελϯεੜ%*ίϯςφͷ ͖ͳ%*ίϯςφʹࠩ͠ସ͑Մೳ 1JNQMF1)1%*"DDMJNBUF $POUBJOFS*OUFSPQ࣮ͷίϯςφ
143࣮ͷίϯςφʢ͔Βʣ
%*ίϯςφͱͷ૬ੑ @@JOWPLFϝιου͕͋ΕΑ͍ͷͰ DPOUSPMMFSNJEEMFXBSF ίϯετϥΫλΠϯδΣΫγϣϯ ҙͷΠϯελϯεΛͤΔ
NPEFMΫϥεͱ͔ɺSFOEFSFSͱ͔
DPOUSPMMFS /** @var \Slim\Views\Twig */ private $view; public fucntion __construct(Twig
$view) { $this->view = $view; } public function __invoke(Request $request, Response $response, array $args): Response { return $this->view->render($response, 'foo.twig'); }
Λͯ͠ɺ143ͷ
ؔ͋Γͦ͏ͳ143 IUUQXXXQIQpHPSHQTS 1)14UBOEBSET3FDPNNFOEBUJPOT 143)551.FTTBHF*OUFSGBDF"DDFQUFE 143$POUBJOFS*OUFSGBDF"DDFQUFE
143)551.JEEMFXBSFT%SBGU
143 "DDFQUFE %*ίϯςφͷJOUFSGBDFͷඪ४Խ 1TSa$POUBJOFSa$POUBJOFS*OUFSGBDF HFUͱIBTͷϝιουΛ࣋ͭ
143 %SBGU .JEEMFXBSF*OUFSGBDF NJEEMFXBSFࣗମʹؔ͢Δͷ %FMFHBUF*OUFSGBDF ҕઌίΞͷΞϓϦϨΠϠʔʁ
·ͩٞͷߦํ͕ఆ·͍ͬͯͳ͍
1)1ͷNJEEMFXBSFྲّྀ %PVCMF1BTT 4MJNͬͪ͜ GO SFRVFTU SFTQPOTF OFYU
SFTQPOTF 4JOHMF1BTT GO SFRVFTU OFYU SFTQPOTF
.JEEMFXBSF*OUFSGBDF namespace Psr\Http\ServerMiddleware; interface MiddlewareInterface { public function process( ServerRequestInterface
$request, DelegateInterface $delegate ): ResponseInterface; }
%FMFHBUF*OUFSGBDF namespace Psr\Http\ServerMiddleware; interface DelegateInterface { public function process( ServerRequestInterface
$request ): ResponseInterface; }
ଞͷϑϨʔϜϫʔΫͷ߹
-BSBWFM IUUQTMBSBWFMDPNEPDT NJEEMFXBSF 143ͳͲҙ͍ࣝͯ͠ͳ͍ ैདྷͷDPOUSPMMFSͷิॿతͳׂ ڞ௨ॲཧΛ࣮͢ΔͨΊͷΈ
-BSBWFMྫ class CheckAge { public function handle( \Illuminate\Http\Request $request, \Closure
$next) { // Կ͔ॲཧʢલͰޙΖͰʣ return $next($request); } } Route::get('/', function() { /* ॲཧ */ }) ->middleware(CheckAge::class);
$BLF1)1 $BLF1)1͔ΒNJEEMFXBSF͕͋Δ ࣮ํ๏4MJNͱ΄ͱΜͲಉ͕ͩ͡ɺ ਖ਼͜ͳΕ͍ͯͳ͍ײ͡ ΫϥεͰͳ͘ΠϯελϯεΛ͢ IUUQTXXXTMJEFTIBSFOFUNBSLTUPSZ
DBLFQIQUIFSPBEBIFBE
4ZNGPOZ NJEEMFXBSFʹ૬͢Δػೳͳ͍ ػೳͱͯ͠ϑΟϧλʔ͕͋Δ 4JMFYͰNJEEMFXBSFͱݺͿͷ͋Δ ͕ɺ͍ΘΏΔϑΟϧλʔͰ͔͠ͳ͍
;FOE&YQSFTTJWF IUUQTEPDT[FOEGSBNFXPSLDPN [FOEFYQSFTTJWF 143.JEEMFXBSF3PVUJOH%* 143ͳͲͷඪ४Λҙࣝ BDUJPOΫϥεNJEEMFXBSFͱ࣮ͯ͠
;FOE&YQSFTTJWFྫ $helloMiddleware = function ( ServerRequestInterface $request, DelegateInterface $delegate )
{ return new TextResponse('Hello', 200); }; // ͋Δ͍MiddlewareInterfaceΛ࣮ͨ͠Ϋϥε $app->get('/hello', $hellosMiddleware);
NJEEMFXBSF ͍͔͕Ͱ͔ͨ͠ʁ
·ͱΊ NJEEMFXBSFͱ͍͏ߟ͑ํΛΔ͜ͱ ॲཧΛNJEEMFXBSFͰׂ➡ςετ༰қੑ 143Ͱඪ४Խ͞ΕΔ͜ͱͰࠩ͠ସ͑Մೳʹ %*ίϯςφͱͷΈ߹Θͤɺศར
4MJNͱ͔;FOE&YQSFTTJWF໘ന͍Αʂ
͋Γ͕ͱ͏͍͟͝·ͨ͠ ࣭͕͋ΕͲ͏ͧ