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
CakePHPの内部実装 から理解するPSR-7
Search
kubo ayumu
June 30, 2022
Programming
1.7k
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
CakePHPの内部実装 から理解するPSR-7
https://lancersrecruit.connpass.com/event/248522/
kubo ayumu
June 30, 2022
More Decks by kubo ayumu
See All by kubo ayumu
MariaDB Connector/C のcaching_sha2_passwordプラグインの仕様について
boro1234
0
1.3k
caching_sha2_passwordのはなし
boro1234
0
2.9k
大テーブルと小テーブルのJOINのコスト計算の話
boro1234
5
2.2k
やさしいActiveRecordのDB接続のしくみ
boro1234
14
9.3k
テーブル定義変更の ガイドラインを作った話
boro1234
2
2.1k
正規化理論ことはじめ -数学的背景から理解する正規化の初手-
boro1234
1
1.2k
RDBおける候補キーを求めるためのアルゴリズム
boro1234
0
1.3k
Other Decks in Programming
See All in Programming
FactoryBotをやめればRSpecは速くなるのか?
yuta_onishi_97
0
1.1k
Vue Fes Japan の “作る側”に関わってみて
naokihaba
1
180
AI-Powered Domain-Driven Design
ziobrando
0
300
Coding with AI: How to trust the storyteller (AWS Community Day Adria, Ljubljana 2026)
slobodan
0
110
dotNET_vulnclicker_intro.pdf
deka_morita
0
150
PumaからFalconに移行したRailsアプリケーションでの実践
falcon8823
0
200
AI主導のプログラミング学習アプリを作ってみた
econanringo
0
190
ジョジョの世界をXRで再現する
mofurune
0
180
Railsバージョンを4倍にした話
optim
0
580
自作Discord音声botをLambda MicroVMsに移行した話 / Migrating My Discord Voice Bot to Lambda MicroVMs
akihisaikeda
0
150
複雑なUIコンポーネントとの ⻑い付き合い⽅:波及するバグからテスト戦略を経て、安全な再設計へ
mixplace
0
450
現場と育てるRailsモデリング 〜Spreadsheetから始めたモデル設計〜
siroemk
2
930
Featured
See All Featured
The SEO Collaboration Effect
kristinabergwall1
1
600
Art, The Web, and Tiny UX
lynnandtonic
304
22k
Producing Creativity
orderedlist
PRO
348
41k
Rails Girls Zürich Keynote
gr2m
96
14k
AI Search: Implications for SEO and How to Move Forward - #ShenzhenSEOConference
aleyda
1
1.4k
The Invisible Side of Design
smashingmag
301
52k
The World Runs on Bad Software
bkeepers
PRO
72
12k
Abbi's Birthday
coloredviolet
4
10k
AI Search: Where Are We & What Can We Do About It?
aleyda
0
8.1k
DevOps and Value Stream Thinking: Enabling flow, efficiency and business value
helenjbeal
2
410
SEO for Brand Visibility & Recognition
aleyda
0
4.8k
Balancing Empowerment & Direction
lara
6
1.3k
Transcript
$BLF1)1ͷ෦࣮ ͔Βཧղ͢Δ143
Confidential © 2018 for LANCERS, Inc. All Rights Reserved 2
2 久保 路(くぼ あゆむ) ・LancersのQAチームに所属 ・CakePHP2→4へのバージョンアップ プロジェクトに参画中 ・クラフトビールが好き
Confidential © 2018 for LANCERS, Inc. All Rights Reserved 3
3 public function add() { if ($this->request->is('post')) { $inputParams = $this->request->getData(); $user = $this->fetchTable('Users')->get($inputParams['id']); …… } }
Confidential © 2018 for LANCERS, Inc. All Rights Reserved 4
4 public function add() { if ($this->request->is('post')) { $inputParams = $this->request->getData(); $user = $this->fetchTable('Users')->get($inputParams['id']); …… } }
Confidential © 2018 for LANCERS, Inc. All Rights Reserved 5
5 public function add() { if ($this->request->is('post')) { $inputParams = $this->request->getData(); $user = $this->fetchTable('Users')->get($inputParams['id']); …… } } ServerRequestのインスタンスであり 仕様はPHPFIGという団体がPSRとして規定
Confidential © 2018 for LANCERS, Inc. All Rights Reserved 6
今⽇はこの$this->requestを ちょっと深掘ってみます
Confidential © 2018 for LANCERS, Inc. All Rights Reserved 7
7 今⽇持ち帰っていただきたいこと ・PSRとは⼀体何なのか ・PSR-7ではどんなインターフェースを定めているのか ・HTTPリクエストとレスポンスは フレームワーク内でどのように扱われているのか
Confidential © 2018 for LANCERS, Inc. All Rights Reserved 8
8 1 PSRって? 2 PSR-7の主張 3 Cakeの内部実装を見てみる(Request編) 4 最後に アジェンダ
143ͬͯʁ
Confidential © 2018 for LANCERS, Inc. All Rights Reserved 10
• PHP-FIGが定める規約 (PHPフレームワーク相互運⽤グループ) • ⽬的 ◦ 共通の仕様を定める ◦ 相互運⽤性を⾼める • 具体例 ◦ インターフェースの仕様 ◦ コーディング規約 ◦ etc… PSRとは
Confidential © 2018 for LANCERS, Inc. All Rights Reserved 11
Confidential © 2018 for LANCERS, Inc. All Rights Reserved 12
Confidential © 2018 for LANCERS, Inc. All Rights Reserved 13
Confidential © 2018 for LANCERS, Inc. All Rights Reserved 14
143ͷओு
Confidential © 2018 for LANCERS, Inc. All Rights Reserved 16
• HTTPメッセージ(リクエスト・レスポンス)に関する インターフェースを定める • リクエストからレスポンスへを⽣成する処理の流れで はなく、それ⾃⾝の仕様を定める(流れはPSR15が定 めている) PSR-7とは
Confidential © 2018 for LANCERS, Inc. All Rights Reserved 17
• インターフェース定義 PSR-7とは Psr¥Http¥MessageInterface Psr¥Http¥RequestInterface Psr¥Http¥ServerRequestInterface Psr¥Http¥ResponseInterface etc: StreamInterface, UriInterface, UploadInterface
Confidential © 2018 for LANCERS, Inc. All Rights Reserved 18
PSR-7とは «interface» Message «interface» Request «interface» Response «interface» ServerRequest extends extends extends
$BLFͷ෦࣮ΛݟͯΈΔ 3FRVFTUฤ
Confidential © 2018 for LANCERS, Inc. All Rights Reserved 20
«interface» Message «interface» Request «interface» Response «interface» ServerRequest extends extends extends
Confidential © 2018 for LANCERS, Inc. All Rights Reserved 21
«interface» Message «interface» Request «interface» Response «interface» ServerRequest extends extends extends
Confidential © 2018 for LANCERS, Inc. All Rights Reserved 22
• クライアントからサーバーへの要求とサーバーからクライアント への応答で構成され、それぞれに共通するメソッドを定義する • メソッド例 ◦ getProtocolVersion ◦ getHeader ◦ getBody ◦ etc.. • 継承インターフェース ◦ RequestInterface ◦ ResponseInterface MessageInterface
Confidential © 2018 for LANCERS, Inc. All Rights Reserved 23
«interface» Message «interface» Request «interface» Response «interface» ServerRequest extends extends extends
Confidential © 2018 for LANCERS, Inc. All Rights Reserved 24
• クライアントが送るリクエストの構成を定義する • リクエストターゲットを取得するためのメソッドやそれを⽤いて 新しいインスタンスを作成するためのメソッドが⽤意されている • メソッド例 ◦ getRequestTarget ◦ getMethod ◦ getUri • 継承インターフェース ◦ ServerRequestInterface RequestInterface
Confidential © 2018 for LANCERS, Inc. All Rights Reserved 25
«interface» Message «interface» Request «interface» Response «interface» ServerRequest extends extends extends
Confidential © 2018 for LANCERS, Inc. All Rights Reserved 26
• サーバーが受け取るリクエストの構成を定義する • RequestInterfaceの拡張であり、リクエストに関連するサーバ情 報が備わっている($_SERVERの内容など) • メソッド例 ◦ getServerParams ◦ getCookieParams ◦ getQueryParams • 実装先 ◦ cakephp/src/Http/ServerRequest.php ServerRequestInterface
Confidential © 2018 for LANCERS, Inc. All Rights Reserved 27
cakephp/src/Http/ServerRequest.php CakePHPでの実例(ServerRequest実装先) /** * A class that helps wrap Request information and particulars about a single request. * Provides methods commonly used to introspect on the request headers and request body. */ class ServerRequest implements ServerRequestInterface { protected $params = [ 'plugin' => null, 'controller' => null, 'action' => null, '_ext' => null, 'pass' => [], ]; public function __construct(array $config = []) { $config += [ 'params' => $this->params, 'query' => [], 'post' => [], 'files' => [], 'cookies' => [], 'environment' => [], 'url' => '', 'uri' => null, 'base' => '', 'webroot' => '', 'input' => null, ]; $this->_setConfig($config); }
Confidential © 2018 for LANCERS, Inc. All Rights Reserved 28
cakephp/src/Http/ServerRequest.php CakePHPでの実例(ServerRequest実装先) /** * A class that helps wrap Request information and particulars about a single request. * Provides methods commonly used to introspect on the request headers and request body. */ class ServerRequest implements ServerRequestInterface { protected $params = [ 'plugin' => null, 'controller' => null, 'action' => null, '_ext' => null, 'pass' => [], ]; public function __construct(array $config = []) { $config += [ 'params' => $this->params, 'query' => [], 'post' => [], 'files' => [], 'cookies' => [], 'environment' => [], 'url' => '', 'uri' => null, 'base' => '', 'webroot' => '', 'input' => null, ]; $this->_setConfig($config); }
Confidential © 2018 for LANCERS, Inc. All Rights Reserved 29
どこでどのようにServerRequetの インスタンスが⽣成されている︖
Confidential © 2018 for LANCERS, Inc. All Rights Reserved 30
cakephp/src/Http/Server.php CakePHPでの実例(ServerRequest⽣成の過 程) public function run(?ServerRequestInterface $request = null,?MiddlewareQueue $middlewareQueue = null): ResponseInterface { $this->bootstrap(); $request = $request ?: ServerRequestFactory::fromGlobals(); $middleware = $this->app->middleware($middleware Queue ?? new Middleware Queue()); if ($this->app instanceof PluginApplicationInterface) { $middleware = $this->app->plugin Middleware($middleware); } $this->dispatchEvent('Server.buildMiddleware', ['middleware' => $middleware]); $response = $this->runner->run($middleware, $request, $this->app); if ($request instanceof ServerRequest) { $request>getSession()->close(); } return $response; }
Confidential © 2018 for LANCERS, Inc. All Rights Reserved 31
cakephp/src/Http/Server.php CakePHPでの実例(ServerRequest⽣成の過 程) public function run(?ServerRequestInterface $request = null,?MiddlewareQueue $middlewareQueue = null): ResponseInterface { $this->bootstrap(); $request = $request ?: ServerRequestFactory::fromGlobals(); $middleware = $this->app->middleware($middleware Queue ?? new Middleware Queue()); if ($this->app instanceof PluginApplicationInterface) { $middleware = $this->app->plugin Middleware($middleware); } $this->dispatchEvent('Server.buildMiddleware', ['middleware' => $middleware]); $response = $this->runner->run($middleware, $request, $this->app); if ($request instanceof ServerRequest) { $request>getSession()->close(); } return $response; }
Confidential © 2018 for LANCERS, Inc. All Rights Reserved 32
cakephp/src/Http/ServerRequestFactory.php CakePHPでの実例(ServerRequest⽣成の過程) public static function fromGlobals( ?array $server = null, ?array $query = null, ?array $parsedBody = null, ?array $cookies = null, ?array $files = null ): ServerRequest { $server = normalizeServer($server ?: $_SERVER); $uri = static::createUri($server); /** @psalm-suppress NoInterfaceProperties */ $sessionConfig = (array)Configure::read('Session') + [ 'defaults' => 'php', 'cookiePath' => $uri->webroot, ]; $session = Session::create($sessionConfig); /** @psalm-suppress NoInterfaceProperties */ $request = new ServerRequest([ 'environment' => $server, 'uri' => $uri, 'cookies' => $cookie ?: $_COOKIE, 'query' => $query ?: $_GET, 'webroot' => $uri->webroot, 'base' => $uri->base, 'session' => $session, 'input' => $server['CAKEPHP_INPUT'] ?? null, ]); $request = static::marshalBodyAndRequestMethod($parsedBody ?? $_POST, $request); $request = static::marshalFiles($files ?? $_FILES, $request); return $request; }
Confidential © 2018 for LANCERS, Inc. All Rights Reserved 33
cakephp/src/Http/ServerRequestFactory.php CakePHPでの実例(ServerRequest⽣成の過程) public static function fromGlobals( ?array $server = null, ?array $query = null, ?array $parsedBody = null, ?array $cookies = null, ?array $files = null ): ServerRequest { $server = normalizeServer($server ?: $_SERVER); $uri = static::createUri($server); /** @psalm-suppress NoInterfaceProperties */ $sessionConfig = (array)Configure::read('Session') + [ 'defaults' => 'php', 'cookiePath' => $uri->webroot, ]; $session = Session::create($sessionConfig); /** @psalm-suppress NoInterfaceProperties */ $request = new ServerRequest([ 'environment' => $server, 'uri' => $uri, 'cookies' => $cookie ?: $_COOKIE, 'query' => $query ?: $_GET, 'webroot' => $uri->webroot, 'base' => $uri->base, 'session' => $session, 'input' => $server['CAKEPHP_INPUT'] ?? null, ]); $request = static::marshalBodyAndRequestMethod($parsedBody ?? $_POST, $request); $request = static::marshalFiles($files ?? $_FILES, $request); return $request; }
Confidential © 2018 for LANCERS, Inc. All Rights Reserved 34
cakephp/src/Http/ServerRequestFactory.php CakePHPでの実例(ServerRequest⽣成の過程) public static function fromGlobals( ?array $server = null, ?array $query = null, ?array $parsedBody = null, ?array $cookies = null, ?array $files = null ): ServerRequest { $server = normalizeServer($server ?: $_SERVER); $uri = static::createUri($server); /** @psalm-suppress NoInterfaceProperties */ $sessionConfig = (array)Configure::read('Session') + [ 'defaults' => 'php', 'cookiePath' => $uri->webroot, ]; $session = Session::create($sessionConfig); /** @psalm-suppress NoInterfaceProperties */ $request = new ServerRequest([ 'environment' => $server, 'uri' => $uri, 'cookies' => $cookie ?: $_COOKIE, 'query' => $query ?: $_GET, 'webroot' => $uri->webroot, 'base' => $uri->base, 'session' => $session, 'input' => $server['CAKEPHP_INPUT'] ?? null, ]); $request = static::marshalBodyAndRequestMethod($parsedBody ?? $_POST, $request); $request = static::marshalFiles($files ?? $_FILES, $request); return $request; }
Confidential © 2018 for LANCERS, Inc. All Rights Reserved 35
アプリケーションやミドルウェアを通して リクエストからレスポンスを⽣成する過程で、 リクエストやサーバー情報が詰まった スーパーグローバル変数からServerRequestオブ ジェクトを⽣成している CakePHPでの実例(ServerRequest⽣成の過 程)
Confidential © 2018 for LANCERS, Inc. All Rights Reserved 36
どんな感じでServerRequetの インスタンスを使っている︖
Confidential © 2018 for LANCERS, Inc. All Rights Reserved 37
cakephp/src/Controller/ControllerFactory.php CakePHPでの実例 public function getControllerClass(ServerRequest $request): ?string { $pluginPath = ''; $namespace = 'Controller'; $controller = $request->getParam('controller', ''); if ($request->getParam('plugin')) { $pluginPath = $request->getParam('plugin') . '.'; } if ($request->getParam('prefix')) { $prefix = $request->getParam('prefix'); …… /** @var class-string<¥Cake¥Controller¥Controller>|null */ return App::className($pluginPath . $controller, $namespace, 'Controller'); }
Confidential © 2018 for LANCERS, Inc. All Rights Reserved 38
cakephp/src/Controller/ControllerFactory.php CakePHPでの実例 public function getControllerClass(ServerRequest $request): ?string { $pluginPath = ''; $namespace = 'Controller'; $controller = $request->getParam('controller', ''); if ($request->getParam('plugin')) { $pluginPath = $request->getParam('plugin') . '.'; } if ($request->getParam('prefix')) { $prefix = $request->getParam('prefix'); …… /** @var class-string<¥Cake¥Controller¥Controller>|null */ return App::className($pluginPath . $controller, $namespace, 'Controller'); }
Confidential © 2018 for LANCERS, Inc. All Rights Reserved 39
アプリケーション実⾏の際に様々なクラスで ServerRequestオブジェクトのプロパティか ら欲しい情報を取得している CakePHPでの実例
Confidential © 2018 for LANCERS, Inc. All Rights Reserved 40
必要な時にグローバル変数から 直接読み込めばいいんじゃないの︖
Confidential © 2018 for LANCERS, Inc. All Rights Reserved 41
スーパーグローバル変数の使⽤には デメリットがある
Confidential © 2018 for LANCERS, Inc. All Rights Reserved 42
スーパーグローバル変数 ・変更可能なので別の場所で書き換えられる可能性がある ・テストがしづらい ServerRequestオブジェクト ・不変であるので安⼼ ・状態を付加する場合はwith~関数を使って新しくインスタ ンスを⽣成する ・テストの時もインスタンス作るだけでOK CakePHPでの実例
࠷ޙʹ
Confidential © 2018 for LANCERS, Inc. All Rights Reserved 44
・PSRとは共通の仕様を定めるための規約であり、 PSR-7ではリクエストとレスポンスの仕様を定めている ・RequestInterfaceではクライアントの送るリクエストを定義し、 ServerRequestInterfaceはサーバーが受け取るリクエストを定義する ・フレームワーク内はServerRequestはグローバル変数をもとに⽣成され、 様々なクラスで適切にそのクラスのプロパティが読み込まれている ・内部実装追いかけるの楽しい まとめ
Confidential © 2018 for LANCERS, Inc. All Rights Reserved 45
ありがとうございました︕
Confidential © 2018 for LANCERS, Inc. All Rights Reserved 46
• HyperTextTransferProtcolの略 • TCPベースの通信プロトコル(それ⾃⾝はレイヤーで⾔うとアプ リケーション層のプロトコル) • HTTP リクエストとは、HTTPで指定されたフォーマットで記述 された(クライアント側からの)要求 • HTTP レスポンスとは、HTTPで指定されたフォーマットで記述 された(サーバー側からの)応答 • 上記をまとめてHTTPメッセージと⾔う HTTPとは
Confidential © 2018 for LANCERS, Inc. All Rights Reserved 47
• クラスが持つべきメソッドの名前や型の定義のみされている (すなわち構成が定義されている。以降その構成をまとめて 「型」と呼ぶ) • その型に従って(implementして)クラスを⽤意することを 「インターフェースを実装する」と⾔う • 同じインターフェースを実装している異なるクラスが作成でき、 それらが交換可能となる(なぜなら型が同じであるから) インターフェースとは