メインメニュー
XAMPP アレンジ
IED
WSL2
-
道具箱
リポジトリ編
フレームワーク編
公開ソフトウェア
メタ
リンク
- PHP ライブラリ
- PHP 言語
apricot:core:application-class目次
Apricot アプリケーションクラス
— y2sunlight 2020-04-25
関連記事
- Apricot コア
- Apricot アプリケーションクラス
さて、準備が出来たのでいよいよコアのクラス群を作って行きたいと思います。
Applicationクラスの仕様
最初にApplicationクラスを作成しますが、その前にApplicationクラスの責任を明確にしておきます。
Applicationクラスの責任
- アプリケーションの初期化
- ルーティングとセキュリティの設定
- ミドルウェアの設定
- アクションの起動
Applicationクラスは、以下の公開メソッドを持っています。詳細はソースコードを参照して下さい。
フロントコントローラ(index.php)から呼び出されるメソッド
公開メソッド 機能 setup(array $app=[]) アプリケーションのセットアップ run(callable $routeDefinitionCallback) アクションの実行 ゲッターメソッド
公開メソッド 機能 getInstance():Application Applicationインスタンスの取得 getSetting($dot = null, $default=null) アプリケーション設定(app.php)の取得 getProjectDir():string プロジェクトフォルダの取得 getConfigDir():string config(一般設定)フォルダの取得 getAssetsDir():string assets(資源)フォルダの取得 getVarDir():string var(データ)フォルダの取得 getPublicDirectory():string public(公開)の取得 getRouteBase():string URIルートベースの取得 getControllerName():string カレントコントローラ名の取得 getActionName():string カレントアクション名の取得
Applicationクラス(暫定版)
以下に暫定版のApplicationクラスを示します。ほとんどの機能は実装できていますが、アクションを実行するメソッド(executeAction)だけが未実装(スタブ)です。
/apricot/core
- Application.php
<?php namespace Core; /** * Application Class */ class Application { /** * Application Instance * var Application */ private static $instance = null; /** * Application Setting * @var array */ private $app = []; /* * Project Directories */ private $projectDir; private $configDir; private $assetsDir; private $varDir; /* * Public Directory */ private $publicDir; /* * Route Base Path */ private $routeBase; /* * Controller Name */ private $controllerName; /* *Action Name; */ private $actionName; /** * Get Project dir * @return string */ public function getProjectDir():string {return $this->projectDir;} /** * Get config dir * @return string */ public function getConfigDir():string {return $this->configDir; } /** * Get assets dir * @return string */ public function getAssetsDir():string {return $this->assetsDir; } /** * Get var dir * @return string */ public function getVarDir():string {return $this->varDir; } /** * Get Public Directory * @return string */ public function getPublicDirectory():string {return $this->publicDir; } /** * Get Route Base Path * @return string */ public function getRouteBase():string {return $this->routeBase; } /** * Get controller Name * @return string */ public function getControllerName():string {return $this->controllerName; } /** * Get Action Name * @return string */ public function getActionName():string {return $this->actionName; } /** * Get Application instance. * @return \Core\Application */ static public function getInstance():Application { if (!self::$instance) { throw new \RuntimeException('Application has not been set.'); } return self::$instance; } /** * Create Application * @param string $projectDir * @param string $publicDir */ function __construct(string $projectDir, string $publicDir) { if (!self::$instance) { // Set Project Directories $this->projectDir = $projectDir; $this->configDir = $projectDir.'/config'; $this->assetsDir = $projectDir.'/assets'; $this->varDir = $projectDir.'/var'; // Set Public Directory $this->publicDir = $publicDir; // Set Route Base Path $routeBase = dirname($_SERVER['SCRIPT_NAME']); if (preg_match('/^[\\.\\\\]$/', $routeBase)) $routeBase=''; $this->routeBase = $routeBase; // Set Dotenv \Dotenv\Dotenv::createImmutable($projectDir)->load(); // Set timezone date_default_timezone_set(env('APP_TIMEZONE','UCT')); self::$instance = $this; } } /** * Get an application setting value * @param string|null $dot Dot-notation key * @param mixed $default * @return mixed */ public function getSetting($dot = null, $default=null) { return array_get($this->app, $dot, $default); } /** * Checks if an application setting key is present * @param string $dot Dot-notation key * @return bool */ public function hasSetting(string $dot):bool { return array_has($this->app, $dot); } /** * Setup Application * @param array $app Application Setting */ public function setup(array $app=[]) { $this->app = $app; // Application setup if (!empty($this->app) && array_key_exists('setup', $this->app)) { foreach($this->app['setup'] as $setup) { $func = require_once $setup; if (!is_callable($func) || ($func()===false)) { throw new \RuntimeException("Application Setup Error: {$setup}"); } } } } /** * Run Application * @param callable $routeDefinitionCallback */ public function run(callable $routeDefinitionCallback) { // Create Dispatcher $dispatcher = \FastRoute\simpleDispatcher($routeDefinitionCallback); // Fetch method and URI from somewhere $httpMethod = $_SERVER['REQUEST_METHOD']; $uri = $_SERVER['REQUEST_URI']; // Strip query string (?foo=bar) and decode URI if (false !== $pos = strpos($uri, '?')) { $uri = substr($uri, 0, $pos); } $uri = rawurldecode($uri); $routeInfo = $dispatcher->dispatch($httpMethod, $uri); switch ($routeInfo[0]) { case \FastRoute\Dispatcher::NOT_FOUND: abort(404, 'Page Not Found'); break; case \FastRoute\Dispatcher::METHOD_NOT_ALLOWED: abort(405, 'Method Not Allowed'); break; case \FastRoute\Dispatcher::FOUND: $handler = $routeInfo[1]; $params = $routeInfo[2]; if (is_callable($handler)) { // Case of callable $handler($params); } elseif(strpos($handler,'@')!==false) { // Case of Controller/Action list($this->controllerName, $this->actionName) = explode('@', $handler); // Ecexute action $this->executeAction($this->controllerName, $this->actionName, $params); } else { abort(500,'Action Not Found'); } break; } } /** * Ecexute action * @param string $controllerName * @param string $actionName * @param array $params */ private function executeAction(string $controllerName, string $actionName, array $params=[]) { // TODO: Stub Version $controller = "\\App\\Controllers\\{$controllerName}"; $instance = new $controller(); call_user_func_array(array($instance, $actionName), $params); } }
Applicationクラスのヘルパー関数
Applicationクラスのゲッターメソッドで良く使用されるものは boilerplates.php にヘルパー関数として追加しておきます。
/apricot/core/helpers
- boilerplates.php
// ... /** * Get application setting value * @param string|null $dot Dot-notation key * @param mixed $default * @return mixed */ function app($dot = null, $default=null) { return Core\Application::getInstance()->getSetting($dot, $default); } /** * Checks if an application setting key is present * @param string $dot Dot-notation key * @return bool */ function app_has($dot = null) { return Core\Application::getInstance()->hasSetting($dot); } /** * Get project directory * @param string|null $default * @return string project directory */ function project_dir($path = null):string { return add_path(Core\Application::getInstance()->getProjectDir(), $path); } /** * Get config directory * @param string $path Sub path, if necessary * @return string config directory */ function config_dir($path = null):string { return add_path(Core\Application::getInstance()->getConfigDir(), $path); } /** * Get assets directory * @param string $path Sub path, if necessary * @return string assets directory */ function assets_dir($path = null):string { return add_path(Core\Application::getInstance()->getAssetsDir(), $path); } /** * Get var directory * @param string $path Sub path, if necessary * @return string var directory */ function var_dir($path = null):string { return add_path(Core\Application::getInstance()->getVarDir(), $path); } /** * Get public directory * @param string $path Sub path, if necessary * @return string public directory */ function public_dir($path = null):string { return add_path(Core\Application::getInstance()->getPublicDirectory(),$path); } /** * Get application URL * @param string $path Sub path, if necessary * @return string URL */ function url($path = null):string { // TODO: APP_URLが無い時は、DomainとProtocolから絶対URLを作る $base = env('APP_URL', Core\Application::getInstance()->getRouteBase()); return add_path($base,$path); } /** * Get file URL With version * @param string $filename * @return string URL */ function url_ver(string $filename) { return url($filename).'?v='.env('APP_VERSION'); } /** * Get routing path * @param string $path Sub path, if necessary * @return string routing path */ function route($path = null):string { return add_path(Core\Application::getInstance()->getRouteBase(),$path); } /** * Get current controller name * @return string name */ function controllerName():string { return Core\Application::getInstance()->getControllerName(); } /** * Get current action name * @return string name */ function actionName():string { return Core\Application::getInstance()->getActionName(); }
Applicationクラスの設定ファイル
Applicationクラスは2つの設定ファイル( app.php と routes.php)を持っています。これらはconfigフォルダ内に保存されています。
app.php
app.php はライブラリとミドルウェアに関する構成とセキュリティーの定義が含まれています。
/apricot/config
- app.php
<?php return [ 'setup' =>[], 'middleware' =>[], 'auth' =>[], 'csrf' =>[], ];
- setup — ライブラリの初期化ファイルの所在(フルパス)
- middleware — ミドルウェアの完全修飾クラス名
- auth — ユーザ認証(セッション認証)の設定
- csrf — CSRFトークンの設定
routes.php
routes.php にはルーティング(URIとアクションの紐づけ)の設定が含まれています。
/apricot/config
- routes.php
<?php //------------------------------------------------------------------- // Route Definition Callback //------------------------------------------------------------------- return function (FastRoute\RouteCollector $r) { $base = Core\Application::getInstance()->getRouteBase(); $r->addGroup($base, function (FastRoute\RouteCollector $r) use($base) { // Home // TODO: Stub Version $r->get('/', function() use($base){ header("Content-type: text/html; charset=utf-8"); echo 'Hello, Apricot!'; }); }); };
ルーティング設定に関してはFastRouteを参照して下さい。
テスト実行
ここまでの実装で一度実行してみましょう。以下のように index.php を編集します。
/apricot/public
- index.php
<?php //------------------------------------------------------------------- // オートローダーの登録 //------------------------------------------------------------------- require dirname(__DIR__).'/vendor/autoload.php'; //------------------------------------------------------------------- // パスの設定 //------------------------------------------------------------------- $project_path = dirname(__DIR__); $public_path = __DIR__; //------------------------------------------------------------------- // アプリケーション初期化 //------------------------------------------------------------------- $application = new Core\Application($project_path, $public_path); // TODO: セッション開始 // アプリケーションセットアップ $application->setup(require_once config_dir('app.php')); //------------------------------------------------------------------- // アクションの実行 //------------------------------------------------------------------- $application->run(require_once config_dir('routes.php'));
Applocationクラスの実装が出来たので、index.php に新しく2つの機能が追加されました。
- アプリケーションのセットアップ
- アクションの起動
ブラウザ上で以下のURLにアクセスしてみて下さい。
http://localhost/ws2019/apricot/public/
次のように表示されます:
Hello, Apricot!
apricot/core/application-class.txt · 最終更新: 2020/06/03 10:19 by tanaka
コメント