【9日目】Laravelを更に理解する

投稿日 最終更新日

2023年7月20日~2023年7月21日

昨日一応書籍の第一章まで終わったけど、書籍だけでなく他の視点からもLaravelを学んでみたいので、今回はPaiza講座をやってみる。

あと、PHPの基礎がやっぱりなってない感じがしたのでそこら辺もやりたい。近道は書籍だと思うんだけど、道が険しい。

MVCとは

Laravel関連を調べるとどうしても目に入ってくるMVCという文字。
なんとなくしかわからないので、ちょっと理解する。

そもそも、MVC=Model View Controllerの略で、この3つの要素が主なプロセスとなるプログラム的なこと。時代、人、使われる技術によってMVCの定義は若干違ったりするっぽいけど、今回はLaravelの定番MVCで考える。

  • Model
    主にデータベースとの連携やデータの処理を行う

  • View
    ユーザーインターフェースの部分の作成。HTMLを生成してユーザーの見える物を作る。LaravelではBladeなるテンプレートエンジンを利用する。

  • Controller
    ModelとViewへの司令官。ルーティングから指示された処理の内容から、適切な命令をModelに行いModelからデータの取得をする。次にそのデータを適切なViewに送るのがControllerの仕事。

処理の流れ的には

  1. HTTPリクエスト

  2. ルーティング

  3. Controller

  4. Model

  5. Controller

  6. View

  7. HTTPレスポンス

と言う感じ。

勿論、データの処理が要らなかったりするならModelのところは飛ばしてController→Viewに行くこともある。

つまり、大まかにはルーティング、モデル、コントローラ、ビューでLaravelは出来ている。
あくまでも大まかに。

PaizaのLaravel講座メモ

  • Paizaの凄さは手軽さにあると思う
    ブラウザで出来るからどんな環境からでもプログラミングを学べてしまうの、スゴイ本当に。
    読み込みが遅いのだけが難点。

  • MVCは早めに理解した方がいい
    書籍でもPaizaでも中盤くらいでMVCをやるんだけど、私は早めに理解しちゃった方が今何やってるかが分かるからいいかなと思った。
    MVCをある程度理解したおかげで今何やってんのかが分かる。

  • オブジェクト指向を若干理解してないときつい
    例えば「$table->string(‘user_name’);」はtableのプロパティにstring型の”user_name”というカラムを追加するときの1行なんだけど、クラスのインスタンス、プロパティを若干でも理解してないと何やってんのか分かんないと思う。

    私は分かんなかったので調べた。
    Laravel自体、全体的にオブジェクト指向志向だね。
    いや、そもそも実践的なプログラム自体がオブジェクト指向志向なのかもしれない。

  • これ絶対paiza→書籍がいい
    やっぱり易しいところから、基礎からしっかり理解するのが大事だなあと。

  • Bladeテンプレートのテンプレート
    BladeがあればWordPressで言うCocoonみたいに、HTMLのテンプレートを使いまわせるみたい。めっちゃええなぁ。

    Bootstrapという有名なテンプレート? webフレームワーク? もあるらしく、画面比率とかに応じて構成を自動調整してくれるみたい。将来的には使いたいね。

とりあえず、Paiza講座Laravel入門編3までやった。人に説明できるレベルではないが、ある程度Laravelを理解したので、書籍に戻る。

Laravelの内部の流れを見る

MVCとかではなく、もっと全体的に、もっと具体的に、もっと詳しくLaravel全体の流れをHTTPリクエストからHTTPレスポンスまで見る。

参考文献や書籍は以下の通り

事前知識

私自身、書籍やQiita記事を漁っていて「これが無いと理解できないな、私にはこれが足りないな」と思った知識を挙げておく

  • クラスについて
    そもそも、Laravelは沢山のクラスで出来ている。
    だから、大前提としてクラスの知識が必要なのは勿論なんだけど、具体的には最低でも以下の知識が無いときつい。私は無いに等しかったので調べた。

    • インスタンス

    • メソッド

    • プロパティ

    • コンストラクタ

  • サービスコンテナ
    上のクラスの要素を理解した上で、Laravelのサービスコンテナというのをなんとなく理解しておきたい。
    右も左もわからない……ちょっとだけわかってきた初心者なので、ここはあくまでもなんとなくで良いと思う。

    簡潔に説明すると、サービスコンテナは「依存関係を考慮したクラスのインスタンス管理」をしてくれるもの。
    例えば、ClassAがClassBを前提として動く場合、通常ClassAを使用するコードは以下のようになる

    $classB = new ClassB();
    $classA = new ClassA($classB);

    要するに、一回ClassBのインスタンスを作んなきゃいけない。しかも、ClassBがClassCを前提としてたら更にClassCのインスタンスを作る必要がある。
    でも、サービスコンテナにこの依存関係を登録しておけば、

    $classA = app()->make(ClassA::class);

    で呼び出すことが出来るという感じ。
    他にもサービスコンテナのメリットはあるっぽいんだけど、とりあえず最初はこれだけを理解していれば良いのではと思う。

    もし、自分でサービスコンテナにクラスを登録したかったりしたかった時に、更に調べればいいのではないかな。

  • ミドルウェア
    ミドルウェアは、ルートで指定された処理を行う前に任意の処理を実行できるプロセス。
    ユーザー認証とか、Requestデータに含まれる値の暗号化とかに使われるっぽい。

全体像から掴む

イメージ図をFigmaで作ってみた。参考元はこちらの書籍

イメージ図の処理の流れ的には、クライアントから左に手を添わせる感じで辿っていけばおk。

簡潔にフローを説明すると

  1. HTTPリクエストを送り、index.phpに到着

  2. index.phpがRequestインスタンス(以下Request)を作成し、RequestをHTTPカーネルに送る

  3. HTTPカーネルは諸々の設定を行い、ルータにRequestを渡す。

  4. ルータがコントローラに処理を指示する前に、実行すべきミドルウェアがあればそれを実行する。

  5. ルータがコントローラにRequestを渡す。

  6. (任意)コントローラは必要であればモデルに指示、Requestから必要なデータを渡す。

  7. (任意)モデルがデータの処理を行い、コントローラにデータを渡す。

  8. (任意)コントローラは必要であればビューにデータを渡す。

  9. (任意)ビューがデータを元にHTMLの生成。

  10. コントローラが必要な処理を行うと、Responseインスタンス(以下Response)を作成し、ミドルウェア→ルータ→HTTPカーネルに渡される。

  11. 最後にHTTPカーネルからindex.phpにResponseを渡し、index.phpはHTTPレスポンスを返す

という感じだと思う。勿論付け焼き刃の知識なので、間違っている、ミスリードしている所がある可能性大。

次は一つ一つ詳しく見ていく

エントリポイント(index.php)

実際のindex.phpコード(一部省略)から、エントリポイントが何をしているのかを見ていく。

// ① オートローダの読み込み
require __DIR__.'/../vendor/autoload.php';

// ② Applicationインスタンス作成しフレームワークの起動
$app = require_once __DIR__.'/../bootstrap/app.php';

// ③ サービスコンテナを利用した HTTPカーネルのインスタンス作成
$kernel = $app->make(Kernel::class);

// ④ HTTPカーネルがRequestインスタンスを処理し、Responseを取得しクライアントに送信。
$response = $kernel->handle(
    $request = Request::capture()
)->send();

// ⑤ アプリケーションの終了処理
$kernel->terminate($request, $response);

①.オートローダの読み込み

オートローダはrequireを使わなくても他のファイルのクラスを利用できるようにしてくれるもの。
Pythonでいえば、importをしなくてもクラスとかを使えるイメージ。

②.Applicationインスタンス作成しフレームワークの起動

Illuminate\Foundation\Application.phpのクラスをインスタンス化してるっぽいから見に行ったんだけど、1427行もあった。
フレームワークの起動をしているのがここらしいので当然といえば当然。

このインスタンスでサービスコンテナやルーティングが使えるようになるみたい。

③.サービスコンテナを利用した HTTPカーネルのインスタンス作成

②で使えるようになったサービスコンテナを使い、HTTPカーネルのインスタンスを作成している。
一応カーネルは中核みたいな意味。

④.HTTPカーネルがRequestインスタンスを処理し、Responseを取得しクライアントに送信。

結構ここがメインなイメージある。

$request = Request::capture()

でリクエストインスタンスを取得してhandleメソッドの引数に入れている。

このhandleメソッドからルータに繋がってミドルウェア、コントローラと処理されていく。
そしてレスポンスが帰ってきて、->send();でHTTPレスポンスを返している感じ。

⑤.アプリケーションの終了処理

HTTPカーネルのterminateというメソッドでアプリケーションの終了処理をしているらしい。よくはわからん。後処理、お掃除するイメージ。

ルータ

ルータといっても、普通のルーティングのこと。

routes/web.phpに定義されたルートの中からRequestインスタンスに合致するルートを探して、ルートに定義された処理を行う。

一応コントローラの処理を実行するだけじゃなく、ここからビューを表示したり、リダイレクトしたり、クラスの処理を実行したりできる。

例えば、以下は/registerパスにPOSTリクエストが来ると、guestというミドルウェアを実行した後に、RegisterControllerというコントローラーを実行する、という意味。

Route::post('/register', [App\Http\Controllers\RegisterController::class, 'store'])
    ->middleware('guest');

以下はコントローラーを通さずにビューを表示している。

Route::get('/', function () {
    return view('welcome');
});

他にもいろいろ出来るので、詳しくは公式ドキュメント(を翻訳してくれているサイト)を。

ミドルウェア

ミドルウェアの主な役割はリクエストをアプリケーションに進める(コントローラに進める)前の処理。でも、アプリケーションで処理したリクエストにミドルウェアを通すこともできる。

ルートにあるように、特定のルーティングにミドルウェアをくっつけることもできるんだけど、グローバルミドルウェアという、全てのリクエストにミドルウェアを付ける方法もある。

こちらも詳しく知りたければ公式ドキュメント(を翻訳してくれているサイト)

コントローラ

教義的にはアプリケーションの実行起点。

簡単に説明できるほど浅いところでない気がする。

様々な処理を行って、Responseを戻り値とする……くらいしか今はわからない。
とにかく、色々できる。

とりあえずLaravelの内部の流れはこんな感じ? 大まかにだけど理解はできた。
Laravelと友達にはなれそうなくらいにはなったのでは。

書籍を進める

とりあえず、書籍を進めていく。

第二章の後半は重要なんだろうけど、ちょっとやる気が出ないので一回スルーさせていただく。

第3章の「MVCとADR」から進めていくんだけど、このタイミングでMVCか。

以下はメモ

  • 名前空間とは
    クラス名、関数名が競合しないようにする仕組み。
    同じクラス名などになるとPHPはエラーを起こしてしまう。

    そこで、クラスや関数を定義するとき、

    namespace group1{  
        class Myclass{}  
    }  
    

    のように名前空間を指定しておくと、次から
    $example = new \group1\Myclass;
    のように被ってても使えるようになる。

    また、事前にuseを使い
    use group1\Myclass;
    としておくことで、エイリアス(ショートカットみたいなもん)を作れて、
    $example = new Myclass;
    で使えるようになるよ。

  • declare(strict_types=1);とは
    declare(strict_types=1);は関数やメソッドでの型を厳格にするモード。
    つまり、関数の引数や戻り値にintと定義しているところにfloatとかが入ってきたらエラーを吐くようになる。
    逆にデフォルトを意味するdeclare(strict_types=0);は型をある程度許容してくれて、intにfloatが入っても、5.0とかならintに直してくれたりする。

    注意点は<?phpの直後に記述する必要があること、影響範囲はそのファイルのみで、他のファイルから呼び出した場合は影響しないとか。

おわりに

なんかトランザクションスクリプトパターンやドメインモデルパターンなどの設計の話も纏めようと思ったんだけど、覗いてみたら底が見えなかったのでとりあえず今日はここまで。

明日は設計をがっつりやる。覗いてみたら滅茶苦茶重要そうで、色んな思想があって、とても深かった。

現在のWEBで使われるMVC、いわゆるMVC2が間違っているのではという話とか、3層アーキテクチャの話とか色々あった。

とりあえず、おやすみなさい。