簡易的なPHPフレームワークを作ってみた
簡易的なフレームワークを実際手を動かして作ることで多少なりとも、
現在使っているフレームワーク(Laravel・自社フレームワーク)の理解の助けになればよいと思い作ってみました。
リクエストの処理をindex.phpに集中させる
.htaccessですべてのリクエストに対してindex.phpが実行されるようにします。
https://sample.jp.localhost/blog/hogehoge
たとえば、上記のようなアクセスがあったら、以下のようなURLにリダイレクトされます。
https://sample.jp.localhost/index.php?url=blog/hogehoge
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
</IfModule>
index.phpはリクエスト時最初に実行されるPHPプログラムです。
.htaccess
でリダイレクトされることによってどのリクエストもまずはこのプログラムを通ります。
require __DIR__ . '/action.php';
$app = new action();
$app->run();
index.phpで読み込ませているaction.php
です。
ここでリクエストを判別してmodels
以下にあるclassを呼び出しています。
<?php
class action {
public function run() {
$GET = filter_input(INPUT_GET, 'url');
$params = explode('/', $GET);
$fileName = array_shift($params);
$filePath = './models/' . $fileName . '.php';
$className = $fileName . '_action';
if ($fileName && file_exists($filePath)) {
require './models/' . $fileName . '.php';
$app = new $className();
extract($app->handle($params)); //viewに変数をアサイン
require './views/' . $fileName . '.php';
} else if(!$fileName || !file_exists($filePath)){
require './models/index.php';
$app = new index_action();
extract($app->handle($params)); //viewに変数をアサイン
require './views/index.php';
}
}
}
models
modelsはGETパラメータが無い時や存在しないURLにリクエストがあったときはindex.php
が読み込まれ、GETパラメータに対応するclassが存在する場合はそれが読み込まれます。
例:https://sample.jp.localhost/blog/
上記のようなリクエストがあった時はblog_actionClass
が読み込まれる。
class blog_action{
function handle($params){
return array(
'title'=>'Hello World! (blog)',
'h1'=>'Hello World! (blog)'
);
}
}
class index_action {
function handle($params) {
return array(
'title'=>'Hello World! (index)',
'h1'=>'Hello World! (index)'
);
}
}
views
viewsはmodels
の方で設定した配列のキーが変数として使用できます。
<html>
<head>
<meta charset="utf-8">
<title><?php echo $title; ?></title>
</head>
<body>
<h1><?php echo $h1; ?></h1>
</body>
</html>
まとめ
「PHP フレームワーク 自作」とかで検索して色んなサイト参考にさせて頂きました。
フレームワークが実際どういう原理で動いているのかいまいち理解できていなかったのですが、
手を動かすことによって多少は理解の助けになった気がします。
普段の業務ではLaravelや自社製のフレームワークなんかを触る機会が多いですが、
フレームワーク機能を極限まで削るとこんな感じなのかなぁと思います。
課題
classを読み込む時はrequireでなくて、autoloaderを使いたかったけどなぜか認識されず要調査。