Slide 1

Slide 1 text

Laravelコアファイルの コードリーディング Model::all()からnew PDO()まで追ってみた Presented by y_sone @20221221_PHP勉強会

Slide 2

Slide 2 text

自己紹介 y_sone ● エンジニア5年目 ● たまにイベントのスタッフをやってます ● @yukinofu815

Slide 3

Slide 3 text

今日話すこと ● なぜコアファイルを読もうと思ったか ● Model::all()からnew PDO()まで追ってみた ● コアファイルを読むメリット

Slide 4

Slide 4 text

なぜコアファイルを読もうと思ったか ● 好奇心 ● 仕事ではコアファイルの奥底まで読むことがないから ● コードリーディングの練習

Slide 5

Slide 5 text

Model::all()からnew PDO()まで追ってみた ● PHPのDB接続といえばnew PDO() ● new PDO()はどこ?

Slide 6

Slide 6 text

DB接続に関連するクラス一覧

Slide 7

Slide 7 text

new PDO()はここで実行されている

Slide 8

Slide 8 text

Model::all()から追ってみよう

Slide 9

Slide 9 text

※ 注意(説明上の呼び方) EloquentBuilder QueryBuilder

Slide 10

Slide 10 text

呼び出し元のArticleController.phpのindex() // app/Http/Controllers/ArticleController.php class ArticleController extends Controller { public function index(Request $request) { $articles = Article::all(); return view('article.index', compact('articles')); } }

Slide 11

Slide 11 text

Article.phpの親クラスModel.phpのall() // vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php public static function all($columns = ['*']) { return static::query()->get( is_array($columns) ? $columns : func_get_args() ); }

Slide 12

Slide 12 text

query()でやること ● Connectionインスタンスの取得 ○ Connectionインスタンスはindex.php実行時にKernelのhandle()で生成済み ○ シングルトンで生成される ● Builderインスタンスの生成 ○ ConnectionインスタンスからQueryBuilderインスタンスを生成 ○ QueryBuilderインスタンスからEloquentBuilderインスタンスを生成

Slide 13

Slide 13 text

get()でやること ● SQLの実行 ● SQLの結果をModelのCollectionとして取得 ● このget()はEloquentBuilderのメソッド ● このget()の中でQueryBuilderのget()も呼ばれる

Slide 14

Slide 14 text

get()でやること(EloquentBuilder編) ● EloquentBuilderはQueryBuilderのインスタンスを保有している ● QueryBuilderのget()を実行 ● QueryBuilderのget()で取得したデータをModelのCollectionに変換

Slide 15

Slide 15 text

get()でやること(EloquentBuilder編) // vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php public function get($columns = ['*']) { $builder = $this->applyScopes(); if (count($models = $builder->getModels($columns)) > 0) { $models = $builder->eagerLoadRelations($models); } return $builder->getModel()->newCollection($models); }

Slide 16

Slide 16 text

get()でやること(EloquentBuilder編) // vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php public function getModels($columns = ['*']) { return $this->model->hydrate( $this->query->get($columns)->all() )->all(); }

Slide 17

Slide 17 text

get()でやること(QueryBuilder編) ● PDOの生成 ● PDOを利用したSQLの実行

Slide 18

Slide 18 text

get()でやること(QueryBuilder編) // vendor/laravel/framework/src/Illuminate/Database/Query/Builder.php public function get($columns = ['*']) { return collect($this->onceWithColumns(Arr::wrap($columns), function () { return $this->processor->processSelect($this, $this->runSelect()); })); }

Slide 19

Slide 19 text

get()でやること(QueryBuilder編) 一部のメソッドです。名前から役割が想像しやすいです。 1. QueryBuilder::runSelect() 2. Connection::select() 3. Connection::run() 4. Connection::getPdo() 5. ConnectionFactory::createConnector() 6. Connector::createPdoConnection()

Slide 20

Slide 20 text

new PDO()を発見! // vendor/laravel/framework/src/Illuminate/Database/Connectors/Connector.php protected function createPdoConnection($dsn, $username, $password, $options) { if (class_exists(PDOConnection::class) && ! $this->isPersistentConnection($options)) { return new PDOConnection($dsn, $username, $password, $options); } return new PDO($dsn, $username, $password, $options); }

Slide 21

Slide 21 text

フレームワークはPHPメソッドの集合体 公式ドキュメントのメソッドをコアファイルで見つけるとフレーム ワークが身近になった気がします!

Slide 22

Slide 22 text

コアファイルを読むメリット ● フレームワークのありがたみが分かる ● 生のコードがフレームワーク内でどのように使われているか知ることできる ● フレームワークの設計思想を味わえる ● バグなどの原因究明がし易くなる

Slide 23

Slide 23 text

ご清聴ありがとうございました!