====== Apricot リクエストクラス ====== --- //[[http://www.y2sunlight.com|y2sunlight]] 2020-05-02// [[apricot:top|Apricot に戻る]] 関連記事 * [[apricot:configuration|Apricot プロジェクトの作成]] * [[apricot:public|Apricot 公開フォルダ]] * Apricot コア * [[apricot:core:top|Apricot コア作成の準備]] * [[apricot:core:application-class|Apricot アプリケーションクラス]] * [[apricot:core:basic-class|Apricot 各種基本コアクラス]] * Apricot リクエストクラス * [[apricot:core:response-class|Apricot レスポンスクラス]] * [[apricot:core:base-controller|Apricot ベースコントローラ]] * [[apricot:core:completion|Apricot コアの完成]] * [[apricot:app:top|Apricot アプリ]] * [[apricot:ext:middleware|Apricot 拡張]] リクエストはPHPの $_GET,$_POST,$_SESSION,$_COOKIE,$_SERVER,$_FILE を対象とします。多くのフレームワークではこれらをまとめて1つのRequestクラスで実装しています。しかし、apricotではなるべく本来のPHPのスタイルを残した形で実装したいと思います。$_GET,$_POST,$_SESSION,$_COOKIEに、FLASH(1回限り有効なセッション変数)を加えてたリクエストを対象として以下の5つのクラスをシングルトンとして実装します。 * Input --- フォーム送信データ(GET変数またはPOST変数) * QueryString --- クエリ文字列(GET変数) * Session ---SESSION変数 * Flash --- 1回限り有効なSESSION変数 * Cookie --- COOKIE変数 これらのクラスを総称してリクエストクラスと呼びます。 尚、$_SERVER変数についてはそのまま使用し、$_FILEについては実装を保留します(必要に応じて外部ライブラリを使うか自作する事になると思います)。 ---- ===== Input ===== Inputクラスはフォームの送信データを取得するクラスです。Inputクラスと後述の[[#QueryStringクラス|QueryStringクラス]]は共に次に説明するSimpleInputクラスを使って実装します。 ==== SimpleInputクラス ==== SimpleInputクラスは入力データを扱うシンプルで汎用的なクラスです。コンストラクタで入力データを与えて初期化し以下のpublicメソッドを持ちます。 * has() --- キー指定よる入力データの存在確認 * get() --- キー指定よる入力データの取得 * all() --- 全ての入力データの取得 * only() --- 必要入力データのみの取得 * except() --- 不要なものを除く入力データの取得 * set() --- 入力データの設定 * remove() --- 入力データの削除 {{fa>folder-open-o}} ** /apricot/core/Foundation ** input = !empty($input) ? $input : array(); } /** * Checks if a key is present * @param string $key * @return boolean */ public function has(string $key):bool { return array_key_exists($key, $this->input); } /** * Get input data * @param string $key * @param string $default * @return mixed */ public function get(string $key, string $default = null) { if ($this->has($key)) { return $this->input[$key]; } else { return $default; } } /** * Get all input data * @return array */ public function all():array { return $this->input; } /** * Get a subset of the input for only specified keys * @param array|mixed $keys array or arguments list * @return array */ public function only($keys):array { $key_arr = is_array($keys) ? $keys : func_get_args(); return array_only($this->input, $key_arr); } /** * Get a subset of the input except for specified keys * @param array|mixed $keys array or arguments list * @return array */ public function except($keys):array { $key_arr = is_array($keys) ? $keys : func_get_args(); return array_except($this->input, $key_arr); } /** * Set input data * @param string $key * @param string $value */ public function set(string $key, string $value) { $this->input[$key] = $value; } /** * Remove input data * @param array|mixed $keys array or arguments list */ public function remove($keys) { $key_arr = is_array($keys) ? $keys : func_get_args(); foreach($key_arr as $key) { if ($this->has($key)) { unset($this->input[$key]); } } } } \\ ==== Inputクラス ==== Inputクラスは、上のSimpleInputクラスをシングルトンにしたもので、SimpleInputのメソッドが全て使用できます。初期化時にHTTPメソッドによってGET変数またはPOST変数の何れかを使用してクラスを生成します。Inputクラスは、フォームの入力データを取得する場合に使用します。 使用法: ** Input::{メソッド} ** ^メソッド^機能^ |bool has(string $key)|キー指定よる入力データの存在確認| |string get(string $key, string $default = null)|キー指定よる入力データの取得| |array all()|全ての入力データの取得| |array only(array|mixed $keys)|必要入力データのみの取得| |array except(array|mixed $keys)|不要なものを除く入力データの取得| |set(string $key, string $vale)|入力データの設定| |remove(string $key)|入力データの削除| {{fa>folder-open-o}} ** /apricot/core ** \\ ===== QueryString ===== QueryStringクラスはクエリ文字列を取得する為のクラスです。フォームデータは(GETメソッドの場合でも)Inputクラスによって取得できるので、このクラスの目的は、POSTメソッドのクエリ文字列を取得する場合に限定されると思います。 ==== QueryStringクラス ==== QueryStringクラスは、上述の[[#SimpleInputクラス|SimpleInputクラス]]をシングルトンにしたもので、SimpleInputのメソッドが全て使用できます。SimpleInputのコンストラクタにGET変数与えてクラスを生成します。 使用法: ** QueryString::{メソッド} ** ^メソッド^機能^ |bool has(string $key)|キー指定よる入力データの存在確認| |string get(string $key, string $default = null)|キー指定よる入力データの取得| |array all()|全ての入力データの取得| |array only(array|mixed $keys)|必要入力データのみの取得| |array except(array|mixed $keys)|不要なものを除く入力データの取得| |set(string $key, string $vale)|入力データの設定| |remove(string $key)|入力データの削除| {{fa>folder-open-o}} ** /apricot/core ** \\ ===== Session ===== Sessionクラスはセッション変数を設定及び取得をするクラスで、SimpleSessionクラスを使って実装します。Sessionクラス後述する[[#Flash|フラッシュデータ]]を包含しています。 ==== SimpleSessionクラス ==== SimpleSessionクラスは$_SESSIONのラッパークラスです。以下のpublicメソッドを持ちます。 * start() --- セッションの開始 * isStarted() --- セッションが開始されているか否かを取得 * has() --- セッション変数の存在確認 * get() --- セッション変数の取得 * set() --- セッション変数の設定 * remove() --- セッション変数の削除 * clear() --- セッション変数のクリア * destroy() --- セッションの破棄 * flash() --- フラッシュデータの取得 {{fa>folder-open-o}} ** /apricot/core/Foundation ** $value) { if (isset($value)) { try { ini_set("session.{$key}", $value); \Core\Debug::debug("ini_set(session.{$key})=".ini_get("session.{$key}")); } catch(\Throwable $e) { \Core\Debug::error("ini_set(session)",[$key,$value]); }; } } } /** * Session Start */ public function start() { // Start Session session_start(); $this->flash = new SimpleFlash(); } /** * Checks if session has started * @return bool */ public function isStarted():bool { return (array_key_exists(session_name(), $_COOKIE)); } /** * Checks if a key is present * @param string $key * @return bool */ public function has(string $key):bool { return array_key_exists($key, $_SESSION); } /** * Get session data * @param string $key * @param mixed $default * @return mixed */ public function get(string $key, $default = null) { if ($this->has($key)) { return $_SESSION[$key]; } else { return $default; } } /** * Set session data * @param string $key * @param mixed $value */ public function set(string $key, $value) { $_SESSION[$key] = $value; } /** * Remove session data * @param string $key */ public function remove(string $key) { if ($this->has($key)) { unset($_SESSION[$key]); } } /** * Clear session data */ public function clear() { $_SESSION = []; } /** * Destroy session data */ public function destroy() { $this->clear(); if($this->isStarted()) { $params = session_get_cookie_params(); setcookie(session_name(), '', time() -24*60*60, $params['path'], $params['domain'], $params['secure'], $params['httponly']); } session_destroy(); } /** * Get flash data * @return \Core\Foundation\SimpleFlash */ public function flash() { return $this->flash; } } * SimpleSessionクラスはフラッシュデータをメンバ($flash)に持っています。 * セッション開始時にフラッシュを生成しています。フラッシュのコンストラクタはセッションからフラッシュデータを再現し一度しか使用できないようにこの時点でデータを削除します。 * コンストラクタで設定ファイルを読み込みセッション名や有効時間などを設定します。 \\ ==== Sessionクラス ==== Sessionクラスは、上のSimpleSessionクラスをシングルトンにしたもので、SimpleSessionのメソッドが全て使用できます。 使用法: ** Session::{メソッド} ** ^メソッド^機能^ |start()|セッションの開始| |isStarted():bool|セッションが開始されているか否かの判定| |has(string $key):bool|セッション変数の存在確認| |get(string $key, $default = null)|セッション変数の取得| |set(string $key, $value)|セッション変数の設定| |remove(string $key)|セッション変数の削除| |clear()|セッション変数のクリア| |destroy()|セッションの破棄| |flash():SimpleFlash|フラッシュデータの取得| {{fa>folder-open-o}} ** /apricot/core ** \\ ==== 設定ファイル ==== セッションには以下の初期設定ファイルが存在します。 {{fa>folder-open-o}} ** /apricot/config/setting ** 'SID'.substr(md5(env('APP_SECRET', env('APP_NAME'))),0,16), 'ini' =>[ 'gc_maxlifetime' => null, /* default: 1440[sec] */ 'gc_probability' => null, /* default: 1 */ 'gc_divisor' => null, /* default: 100 */ 'cookie_lifetime' => null, /* default: 0[sec] */ ], ]; * name --- シークレット文字列([[apricot:core:top#環境設定|APP_SECRET]])を使ってセッション名を設定します * ini.gc_maxlifetime --- サーバに保存されるセッション変数の有効期間(既定値は1440[秒]) * ini.gc_probability --- [[https://www.php.net/manual/ja/session.configuration.php#ini.session.gc-probability|PHPのマニュアル]]を参照して下さい(既定値は1) * ini.gc_divisor --- [[https://www.php.net/manual/ja/session.configuration.php#ini.session.gc-divisor|PHPのマニュアル]]を参照して下さい(既定値は100) * ini.cookie_lifetime --- セッションクッキーの有効期間(既定値0ではブラウザを閉じたらセッションは破棄されます) \\ ===== Flash ===== フラッシュとは、セッション内で一回限りだけ有効な[[#Session|セッション]]変数のことです。Flashクラスはフラッシュ変数の設定及び取得を行うクラスで、SimpleFlashクラスを使って実装します。 ==== SimpleFlashクラス ==== SimpleFlashクラスは以下のpublicメソッドを持ちます。 * has() --- フラッシュ変数の存在確認 * get() --- フラッシュ変数の取得 * set() --- フラッシュ変数の設定 * remove() --- フラッシュ変数の削除 * clear() --- フラッシュ変数のクリア {{fa>folder-open-o}} ** /apricot/core/Foundation ** flash = array_key_exists(self::FLASH,$_SESSION) ? $_SESSION[self::FLASH] : array(); Debug::debug($this); unset($_SESSION[self::FLASH]); } /** * Checks if a key is present * @param string $key * @return boolean */ public function has(string $key):bool { return array_key_exists($key, $this->flash); } /** * Get flash data * @param string $key * @param mixed $default * @return mixed */ public function get(string $key, $default = null) { if ($this->has($key)) { return $this->flash[$key]; } else { return $default; } } /** * Set flash data * @param string $key * @param mixed $value */ public function set(string $key, $value) { $_SESSION[self::FLASH][$key] = $value; $this->flash[self::FLASH] = $value; } /** * Remove flash data * @param array|mixed $keys array or arguments list */ public function remove(string $key) { if ($this->has($key)) { unset($_SESSION[self::FLASH][$key]); unset($this->flash[$key]); } } /** * Clear flash data */ public function clear() { unset($_SESSION[self::FLASH]); $this->flash = array(); } } * SimpleFlashクラスのコンストラクタでは、セッション変数からフラッシュ変数を再現し、一度しか使用できないようにこの時点でセッション変数からフラッシュデータを削除します。 \\ ==== Flashクラス ==== Flashクラスは、上のSimpleFlashクラスをシングルトンにしたもので、SimpleFlashのメソッドが全て使用できます。 使用法: ** Flash::{メソッド} ** ^メソッド^機能^ |has(string $key):bool|フラッシュ変数の存在確認| |get(string $key, $default = null)|フラッシュ変数の取得| |set(string $key, $value)|フラッシュ変数の設定| |remove(string $key)|フラッシュ変数の削除| |clear()|フラッシュ変数のクリア| {{fa>folder-open-o}} ** /apricot/core ** * 親クラスが Singleton ではなく CallStatic である点に注意して下さい。 * getInstance()では、単に Sessionオブジェクトのフラッシュデータを返しているだけです。FlashオブジェクトはSessionオブジェクトに包含されています。 \\ ===== Cookie ===== Cookieクラスはクッキーの設定及び取得を行うクラスで、SimpleCookieクラスを使って実装します。 ==== SimpleCookieクラス ==== SimpleCookieクラスは$_COOKIEのラッパークラスです。以下のpublicメソッドを持ちます。 * has() --- クッキーの存在確認 * get() --- クッキーの取得 * set() --- クッキーの設定(有効期限付き) * forever() --- クッキーの設定(永続的) * remove() --- クッキーの削除 {{fa>folder-open-o}} ** /apricot/core/Foundation ** cookie = !empty($_COOKIE) ? $_COOKIE : array(); } /** * Checks if a key is present * @param string $key * @return boolean */ public function has(string $key):bool { return array_key_exists($key, $this->cookie); } /** * Get cookie data * @param string $key * @param string $default * @return string|null */ public function get(string $key, string $default = null) { if ($this->has($key)) { return $this->cookie[$key]; } else { return $default; } } /** * Set cookie data * @param string $key * @param string $value * @param int $expires_sec (not time()*60*60, but 60*60 ) * @return bool return true if successfuly */ public function set(string $key, string $value, int $expires_sec=0):bool { if($this->sendCookie($key, $value, $expires_sec)) { $this->cookie[$key] = $value; return true; } return false; } /** * Set Cookie forever * @param string $key * @param string $value * @return bool return true if successfuly */ public function forever(string $key, string $value):bool { return $this->set($key, $value, config('cookie.forever',self::FOREVER)); } /** * Remove Cookie * @param string $key */ public function remove(string $key) { if ($this->has($key)) { unset($this->cookie[$key]); $this->sendCookie($key, '', -3600); } } /** * Send Cookie * @param string $key * @param string $value * @param int $expires_sec (not time()*60*60, but 60*60 ) * @return bool return true if successfuly */ private function sendCookie(string $key, string $value, int $expires_sec=0):bool { $expires = ($expires_sec==0) ? 0 : time() + $expires_sec; $path = config('cookie.path',''); $domain = config('cookie.domain',''); $secure = config('cookie.secure',FALSE); $httponly = config('cookie.httponly',FALSE); return setcookie($key, $value, $expires, $path, $domain, $secure, $httponly); } } * クッキーの送信(sendCookie)では設定ファイルから必要なパラメータを取得しています。 \\ ==== Cookieクラス ==== Cookieクラスは、上のSimpleCookieクラスをシングルトンにしたもので、SimpleCookieのメソッドが全て使用できます。 使用法: ** Cookie::{メソッド} ** ^メソッド^機能^ |has(string $key):bool|クッキーの存在確認| |get(string $key, $default = null)|クッキーの取得| |set(string $key, string $value, int $expires_sec=0):bool|クッキーの設定(有効期限付き)| |forever(string $key, string $value):bool|クッキーの設定(永続的)| |remove(string $key)|クッキーの削除| {{fa>folder-open-o}} ** /apricot/core ** \\ ==== 設定ファイル ==== クッキーには以下の初期設定ファイルが存在します。 {{fa>folder-open-o}} ** /apricot/config/setting ** '', 'domain' => '', 'secure' => FALSE, 'httponly' => FALSE, ]; * path --- ドメイン上のクッキーが有効なパス(既定値はカレントパス:即ち公開パスpublic) * domain--- クッキーが有効なドメイン(既定値はカレントURLのドメイン) * secure--- TRUEを設定すると、セキュアな接続が存在する場合にのみクッキーを設定します * httponly--- TRUEを設定すると、HTTPを通してのみクッキーを設定します > 設定値の詳細は、PHPマニュアルの[[https://www.php.net/manual/ja/function.setcookie.php|setcookie]]を参照して下さい。 \\ ===== ヘルパー関数 ===== リクエスト処理用のヘルパー関数に追加します。inputLabels()はInputクラスからバリデーションの項目名を取得するのに便利な関数です。その他のget()メソッドはHTMLテンプレートでよく使われる関数です。 ^ヘルパー関数^機能^ |inputLabels\\ (string $message_key):array|フォームデータのラベル配列を取得します| |input\\ (string $key, $default=null):string|フォームデータを取得| |queryString\\ (string $key, $default=null):string|クエリ文字列を取得| |session\\ (string $key, $default=null):mixed|セッション変数を取得| |flash\\ (string $key, $default=null):mixed|フラッシュ変数を取得| |cookie\\ (string $key, $default=null):string|クッキー変数を取得| {{fa>folder-open-o}} ** /apricot/core/helpers ** /** * Get Input Labels * @param string $message_key * @return array */ function inputLabels(string $message_key):array { $labels = []; foreach(array_keys(Core\Input::all()) as $name) { $dot_key = "{$message_key}.{$name}"; if (Core\Lang::has($dot_key)) { $labels[$name] = Core\Lang::get($dot_key); } } return $labels; } /** * Get input($_GET or $_POST depending on the method) data * @param string $key * @param mixed $default * @return string */ function input(string $key, $default=null) { return Core\Input::get($key, $default); } /** * Get QueryString data * @param string $key * @param mixed $default * @return string */ function queryString(string $key, $default=null) { return Core\QueryString::get($key, $default); } /** * Get session($_SESSION) date * @param string $key * @param mixed $default * @return mixed */ function session(string $key, $default=null) { return Core\Session::get($key, $default); } /** * Get flash date * @param string $key * @param mixed $default * @return mixed */ function flash(string $key, $default=null) { return Core\Flash::get($key, $default); } /** * Get cookie($_COOKIE) date * @param string $key * @param mixed $default * @return string */ function cookie(string $key, $default=null) { return Core\Cookie::get($key, $default); } \\