【PHP】自作MVCフレームワークを写経して学んだこと
動機
「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