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
CakePHPの内部実装 から理解するPSR-7
Search
kubo ayumu
June 30, 2022
Programming
1.6k
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.2k
caching_sha2_passwordのはなし
boro1234
0
2.7k
大テーブルと小テーブルのJOINのコスト計算の話
boro1234
5
2.1k
やさしいActiveRecordのDB接続のしくみ
boro1234
14
9k
テーブル定義変更の ガイドラインを作った話
boro1234
2
1.7k
正規化理論ことはじめ -数学的背景から理解する正規化の初手-
boro1234
1
1.2k
RDBおける候補キーを求めるためのアルゴリズム
boro1234
0
1.3k
Other Decks in Programming
See All in Programming
C# and C++ Interoperability - cho-dotnetnew
harukasao
0
280
なぜ型を書くのか? TSKaigi2026で改めて考える #tskaigi_smarthr
kajitack
0
100
Composerを使ったサプライチェーン攻撃の様子を眺めてみる #phpstudy
o0h
PRO
2
250
JavaDoc 再入門
nagise
1
370
Honoでのサプライチェーン侵害対策 〜 3つのライブラリに学ぶ
yusukebe
6
1.3k
セキュリティの専門家じゃなくてもできる。「セキュリティ意識」をアップデートして サプライチェーン攻撃への耐性を高めよう。
tk3fftk
5
890
Language Server 使ってる? 〜VSCode と Zed の場合〜 / Are you using a Language Server? ~For VS Code and Zed~
handlename
0
800
Mujeres en SEO Summit 2026 - Greatest Disaster Hits en Web Performance
guaca
0
190
TAKTでAI駆動開発の品質を設計する
j5ik2o
7
1.4k
The ROI of Quarkus for Spring Boot Applications
hollycummins
0
120
Vite+ Unified Toolchain for the Web
naokihaba
0
320
メソッドのジェネリクスでGoの夢は広がるか? / Kyoto.go #65
utgwkk
3
850
Featured
See All Featured
Ruling the World: When Life Gets Gamed
codingconduct
0
260
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
47
8.2k
WCS-LA-2024
lcolladotor
0
650
Faster Mobile Websites
deanohume
310
31k
Leading Effective Engineering Teams in the AI Era
addyosmani
9
2.1k
Testing 201, or: Great Expectations
jmmastey
46
8.2k
Information Architects: The Missing Link in Design Systems
soysaucechin
0
970
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
17k
Evolving SEO for Evolving Search Engines
ryanjones
0
220
Discover your Explorer Soul
emna__ayadi
2
1.1k
HU Berlin: Industrial-Strength Natural Language Processing with spaCy and Prodigy
inesmontani
PRO
0
410
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
254
22k
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して)クラスを⽤意することを 「インターフェースを実装する」と⾔う • 同じインターフェースを実装している異なるクラスが作成でき、 それらが交換可能となる(なぜなら型が同じであるから) インターフェースとは