📖

【PHP】自作MVCフレームワークを写経して学んだこと

2022/09/20に公開

動機

「Laravelのコントリビューターになりたいなあ・・・。 MVCフレームワーク作ってみればLaravelの中身読みやすくなるのでは!?」となったので早速実践。

教材

教材はudemyのWrite PHP Like a Pro: Build a PHP MVC Framework From Scratchを写経

パーフェクトPHPでもいいが、本を書き写すのしんどそうだったのでこちらの教材にした。
(どちらもPHP5で書かれているのが難点)

学んだこと

Controller

URLパスからどうやってControllerを識別しているのか謎だったが、$_SERVER['QUERY_STRING']でURLパスを取得し、あらかじめ作成したルーティングとマッチするかどうか判別していた。

コントローラーファイル毎にrequireを行うのは非効率なため、spl_autoload_register()
requireを行う。(spl_autoload_register初めて知った・・・)

spl_autoload_register(function ($class) {
    $root = dirname(__DIR__);   // get the parent directory

    $file = $root . '/' . str_replace('\\', '/', $class) . '.php';

    if (is_readable($file)) {
        require $root . '/' . str_replace('\\', '/', $class) . '.php';
    }
});

View

Viewに関してはControllerで指定されたファイルをrequireで渡す

public static function render(string $view, array $args = [])
    {
        extract($args, EXTR_SKIP);

        $file = "../App/Views/$view";  // relative to Core directory

        if (is_readable($file)) {
            require $file;
        } else {
            throw new \Exception("$file not found");
        }
    }

controllerからviewにどうやって変数渡すんだろと思っていたが本教材ではextract関数で定義を行っていた。
Laravelではviewヘルパに変数を渡しているがどのようにやってるんだろう。

Model

PDOによってデータベースに依存することなく、接続ができ、クエリも実行できる。

protected static function getDB(): ?PDO
    {
        static $db = null;

        if ($db === null) {
            $dsn = 'mysql:host=' . Config::DB_HOST . ';dbname=' . Config::DB_NAME . ';charset=utf8';
            $db = new PDO($dsn, Config::DB_USER, Config::DB_PASSWORD);

            $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        }

        return $db;
    }

おそらくLaravelでも同じようにやっているのかな。

まとめ

MVCは理解と実装が難しすぎるものだと思っていたがやってみるとそうでもない。
Laravelに頼りすぎて、PHPについて知らないことばかりなのに気が付いた。

Laravelに触り始めたばかりの人ほど、生PHPでぜひMVCフレームワークを作ってみてほしいです。

参考

Write PHP Like a Pro: Build a PHP MVC Framework From Scratch
Laravelのcontrollerのactionが呼ばれるまでを覗きたい

Discussion