内容へ移動
Ground Sunlight
Windowsで作る - PHPプログラミングの開発環境
ユーザ用ツール
ログイン
サイト用ツール
検索
ツール
文書の表示
以前のリビジョン
バックリンク
最近の変更
メディアマネージャー
サイトマップ
ログイン
>
最近の変更
メディアマネージャー
サイトマップ
トレース:
apricot:core:top
この文書は読取専用です。文書のソースを閲覧することは可能ですが、変更はできません。もし変更したい場合は管理者に連絡してください。
====== Apricot コア作成の準備 ====== --- //[[http://www.y2sunlight.com|y2sunlight]] 2020-04-25// [[apricot:top|Apricot に戻る]] 関連記事 * [[apricot:configuration|Apricot プロジェクトの作成]] * [[apricot:public|Apricot 公開フォルダ]] * Apricot コア * Apricot コア作成の準備 * [[apricot:core:application-class|Apricot アプリケーションクラス]] * [[apricot:core:basic-class|Apricot 各種基本コアクラス]] * [[apricot:core:request-class|Apricot リクエストクラス]] * [[apricot:core:response-class|Apricot レスポンスクラス]] * [[apricot:core:base-controller|Apricot ベースコントローラ]] * [[apricot:core:completion|Apricot コアの完成]] * [[apricot:app:top|Apricot アプリ]] * [[apricot:ext:middleware|Apricot 拡張]] まずは、apricotのコアを作る為に以下を準備します。 * アプリケーションに追加する環境変数(phpdotenv) * コアフォルダ、名前空間、オートローディングの設定 * コア構築のヘルパーとなるグローバル関数とベースクラス ---- ===== 環境設定 ===== アプリケーション全体の環境設定は [[basic-library:phpdotenv:4.1|phpdotenv]] で行います。phpdotenvで使用する環境ファイル( .env ) はプロジェクトフォルダ直下に設置します。 {{fa>folder-open-o}} ** /apricot ** <code ini .env> # Application APP_NAME=Apricot APP_VERSION=0.9 #APP_SECRET=Please set a random 32 characters APP_SECRET=0123456789ABCEDF0123456789ABCEDF APP_DEBUG=true APP_TIMEZONE=Asia/Tokyo APP_LANG=ja # Loging LOG_NAME ="apricot" LOG_LEVEL = "debug" </code> ^環境変数^設定内容^型^必須^ |APP_NAME|アプリケーション名(半角英数字)|string|〇| |APP_VERSION|バージョン|string|〇| |APP_SECRET|シークレット文字列\\ 安全の為にランダムな32文字を設定して下さい|string|〇| |APP_DEBUG|デバッグモード|bool|〇| |APP_TIMEZON|タイムゾーン|string|〇| |LOG_NAME|ログ名 (省略時はAPP_NAMEと同じ)|string| | |LOG_LEVEL|[[https://github.com/Seldaek/monolog/blob/master/doc/01-usage.md#log-levels|ログレベル]] (省略時はdebug)|string| | \\ ===== フォルダの作成 ===== === coreフォルダ === 以下に示すようにプロジェクトフォルダ下に、コア用のフォルダ core を作成し、その下に4つのフォルダ(Derivations, Exceptions, Foundation, helpers)を作成します。 <code> apricot [プロジェクト] | ├── core [Apricotのコア] | | | ├── Derivations [ライブラリの派生クラス] | ├── Exceptions [例外] | ├── Foundation [基盤] | └── helpers [ヘルパー関数] </code> * core フォルダは[[https://www.php-fig.org/psr/psr-4/|PSR-4]]によるオートローディングのベースフォルダとなります。従って、core 下のフォルダ及びファイルはPSR-4の命名規則に従う必要があり、クラスを保存するフォルダ及びファイルはUpperCamelCaseを使用します。それ以外はsnake_caseを使用します。 === configフォルダ === 同様に、アプリケーション設定用のフォルダ config を作成し、その下に2つのフォルダ(setting, setup)を作成します。 <code> apricot [プロジェクト] | ├── config [設定ファイル] | | | ├── setting [機能別の一般設定] | └── setup [機能別の起動設定] </code> === assetsフォルダ === 同様に、リソース用のフォルダ assets を作成し、その下に3つのフォルダ(lang, sql, views)を作成します。 <code> apricot [プロジェクト] | ├── assets [リソース] | | | |── lang [言語別の出力テキスト] | |── sql [SQLファイル] | └── views [HTMLテンプレート] </code> === var フォルダ === 同様に、フォルダ var を作成し、その下に3つのフォルダ(cache, db, logs)を作成します。 <code> apricot [プロジェクト] | ├── var | | | ├── cache [キャッシュ] | ├── db [DBファイル(sqlite)] | └── logs [ログ] </code> \\ ===== 例外クラス ===== Exceptionを継承した2つの例外クラスを core\Exceptions に作成します。 * HttpExceptionクラス --- HTTP例外(HTTPステータスコード400番台,500番台) * TokenMismatchExceptionクラス --- トークンミスマッチ例外(CSRFトークンなどの不一致) {{fa>folder-open-o}} ** /apricot/core/Exceptions ** <code php HttpException.php> <?php namespace Core\Exceptions; /** * Http Exception */ class HttpException extends \Exception { /** * Http Status Code * @var int */ private $statusCode; /** * Create HttpException * @param int $statusCode * @param string $message * @param int $code * @param \Exception $previous */ public function __construct(int $statusCode, string $message = null, int $code = 0, \Exception $previous = null) { $this->statusCode = $statusCode; parent::__construct(isset($message) ? $message : "Http Status : {$statusCode}", $code, $previous); } /** * Get Http Status Code * @return int */ public function getStatusCode() { return $this->statusCode; } } </code> <code php TokenMismatchException.php> <?php namespace Core\Exceptions; /** * Token Mismatch Exception */ class TokenMismatchException extends \Exception { /** * Create TokenMismatchException * @param string $message * @param int $code * @param \Exception $previous */ public function __construct(string $message = 'Token Mismatch Exception', int $code = 0, \Exception $previous = null) { parent::__construct($message, $code, $previous); } } </code> \\ ===== ヘルパー ===== グローバル関数を保存するためのPHPファイルを core\helpers に作成します。目的別に2種類のPHPファイルがあります。 * boilerplates.php --- apricotでよく使用される定型文的なコードパターンを関数化したもの\\ ( apricotではボイラープレートと呼んでいる ) * utilities.php --- PHPの組み込み関数を拡張した関数群\\ ( apricot内部で使用することが主な目的 ) \\ ==== boilerplates.php ==== boilerplates.php へは関数を逐次追加します。現段階での内容は以下の通りです。 ^関数^機能^ |env($key, $default = null)|環境変数(.envファイル設定値)の取得| |abort(int $code, string $message=null)|HTTP例外(400,500番台)の発生| <code php boilerplates.php> <?php /** * Get Environment Variable * @param string $key * @param mixed $default * @return mixed environment Variable */ function env($key, $default = null) { $value = getenv($key); if ($value === false) { return $default; } switch (strtolower($value)) { case 'true': return true; case 'false':return false; case 'empty':return ''; case 'null' :return null; } return $value; } /** * Abort * @param int $code * @param string $message * @throws \Core\Exceptions\HttpException */ function abort(int $code, string $message=null) { throw new Core\Exceptions\HttpException($code, $message); } </code> \\ ==== utilities.php ==== utilities.php にはapricot内部で使用する様々な関数が実装さいれています。ほとんどの場合、アプリケーションから使用することはないと思います。使用法などは以下のソースコードを参照して下さい。 {{fa>folder-open-o}} ** /apricot/core/helpers ** <code php utilities.php> <?php /** * Add path * @param string $base Base path * @param string $path Sub path, if necessary * @return string path */ function add_path(string $base, string $path = null) : string { return (is_null($path)) ? $base : rtrim($base,'/').'/'.$path; } /** * Convert a multi-dimensional associative array to a Dot-notation array * @param array $hash multi-dimensional associative array * @param string $prepend * @return array a Dot-notation array */ function array_dot(array $hash, $prepend = '') { $dot_arry = []; foreach ($hash as $key => $value) { if (is_array($value) && count($value)) { $dot_arry = array_merge($dot_arry, array_dot($value, $prepend.$key.'.')); } else { $dot_arry[$prepend.$key] = $value; } } return $dot_arry; } /** * Get an item from an array using Dot-notation * @param array $hash multi-dimensional associative array * @param string $dot key using Dot-notation * @param mixed $default * @return mixed */ function array_get(array $hash, string $dot=null, $default=null) { if (!isset($dot)) return $hash; $keys = explode('.', $dot); foreach($keys as $key) { if (array_key_exists($key, $hash)) { $hash = $hash[$key]; } else { return $default; } } return $hash; } /** * Checks if a key is present in an array using Dot-notation * @param array $hash multi-dimensional associative array * @param string $dot key using Dot-notation * @return bool */ function array_has(array $hash, string $dot):bool { $keys = explode('.', $dot); foreach($keys as $key) { if (array_key_exists($key, $hash)) { $hash = $hash[$key]; } else { return false; } } return true; } /** * Get a subset of the input for only specified items * @param array $input * @param array|mixed $keys * @return array subset of the input */ function array_only(array $input, $keys) { $key_arr = is_array($keys) ? $keys : array_slice(func_get_args(),1); $results = []; foreach ($key_arr as $key) { $results[$key] = $input[$key]; } return $results; } /** * Get a subset of the input except for specified items * @param array $input * @param array|mixed $keys * @return array subset of the input */ function array_except(array $input, $keys=null) { $key_arr = is_array($keys) ? $keys : array_slice(func_get_args(),1); $results = []; foreach($input as $key=>$value) { if (!in_array($key,$key_arr)) $results[$key]=$value; } return $results; } /** * Generate random numbers * @param number $length * @return string */ function str_random($length = 32) { return substr(bin2hex(random_bytes($length)), 0, $length); } /** * Get short class name * @param object $object * @return string */ function get_short_class_name($object) { return (new \ReflectionClass($object))->getShortName(); } /** * Get snake_case from UpperCamelCase or lowerCamelCase * @param string $camel * @return string|null */ function snake_case(string $camel =null) { if (!isset($camel)) return null; $snake = preg_replace('/([A-Z])/', '_$1', $camel); return ltrim(strtolower($snake), '_'); } /** * Get SQL text from a file * @param string $filename * @return array */ function file_get_sql(string $filename):array { if (!file_exists($filename)) return []; // Read a file $text = file_get_contents($filename); $text = str_replace(["\r\n","\r"], "\n", $text); // Remove comment $text = preg_replace("/\/\*.*?\*\//s", '', $text); $text = preg_replace("/--.*?$/m", '', $text); // Split SQL text $sql = preg_split("/\s*;\s*/", $text); array_walk($sql, function(&$item){ $item = trim($item); }); $sql = array_filter($sql, function($val){ return !empty(trim($val)); }); return $sql; } </code> \\ ===== ベースクラス ===== apricotでは、設定管理、ログ、デバッグバー、HTMLテンプレート、トランスレーションなどのクラスをシングルトンとして実装します。そして、それらのシングルトンのメソッドを静的にアクセス出来るようにします。これらの仕組みを実装する為に、core\Foundation に次の2つのベースクラスを作ります。 * CallStaticクラス --- インスタンスメソッドを静的アクセス可能にするクラス * Singletonクラス --- CallStaticから継承したシングルトン {{fa>folder-open-o}} ** /apricot/core/Foundation ** <code php CallStatic.php> <?php namespace Core\Foundation; /** * CallStatic */ abstract class CallStatic { protected static abstract function getInstance(); /** * Handle calls to Instance,Statically. * @param string $method * @param array $args * @return mixed */ public static function __callStatic($method, $args) { $instance = static::getInstance(); return $instance->$method(...$args); } } </code> <code php Singleton.php> <?php namespace Core\Foundation; /** * Singleton */ abstract class Singleton extends CallStatic { protected static abstract function createInstance(); /** * Get instance. * @return object */ public static function getInstance() { static $instance = null; if (!$instance) { $instance = static::createInstance(); } return $instance; } } </code> \\ ===== オートローディングの変更 ===== 以下のようにcomposer.jsonへ ''autoload'' を追加します。 {{fa>folder-open-o}} ** /apricot ** <code json composer.json> { .... "require" : { ... }, "autoload" : { "psr-4" : { "Core\\" : "core/" }, "files": [ "core/helpers/utilities.php", "core/helpers/boilerplates.php" ] } } </code> * coreフォルダをCore名前空間にマッピングします * 次のファイルをオートロードの対象に追加します(グローバル関数用) * core/helpers/utilities.php * core/helpers/boilerplates.php オートローディングファイルを更新する為に、プロジェクトフォルダで以下のコマンドを実行します。 <code> composer dump-autoload </code> \\
apricot/core/top.txt
· 最終更新: 2020/06/03 10:02 by
tanaka
ページ用ツール
文書の表示
以前のリビジョン
バックリンク
文書の先頭へ