— y2sunlight 2020-05-04
関連記事
HTTPレスポンスには以下の3ケースがあります。
ここでは、正常レスポンスについて扱います。エラーレスポンスは集約例外ハンドラー経由で処理されます。
Responseクラスはレスポンスのベースクラスで、その目的はHTMLヘッダーとフラッシュデータの管理です。後述の RenderResponse(レンダリング用) と RedirectResponse(リダイレクト用) はResponseクラスから派生します。Responseクラスは以下のメソッドを持ちます。
メソッド | 機能 |
---|---|
addHeader($headers):Response | HTMLヘッダーの追加 |
hasFlash(string $key):bool | フラッシュデータの存在確認 |
addFlash(string $key, $value):Response | フラッシュデータの追加 |
commit(int $response_code=null) | レスポンスの確定 |
/apricot/core/Foundation
<?php namespace Core\Foundation; use Core\Session; /** * Improvised Response Class */ class Response { /** * * @var array */ protected $headers = []; /** * * @var array */ protected $flashes = []; /** * Flash key for old inputs */ public const FLASH_KEY_OLD = '_old_inputs'; /** * Flash key for old URL Path */ public const FLASH_KEY_BACK = '_old_path'; /** * Flash key for error bag */ public const FLASH_KEY_ERRORS = 'errors'; /** * Add a header * @param string|array $headers * @return Response */ public function addHeader($headers):Response { $header_arr = is_array($headers) ? $headers : [$headers]; foreach($header_arr as $header) { $this->headers[] = $header; } return $this; } /** * Check if a flash value is present * @param string $key * @return bool */ public function hasFlash(string $key):bool { return array_key_exists($key, $this->flashes); } /** * Add a value to flash * @param string $key * @param mixed $value * @return Response */ public function addFlash(string $key, $value):Response { $this->flashes[$key] = $value; return $this; } /** * Commit Response Data * @param int $response_code */ public function commit(int $response_code=null) { // Set Http response code if (isset($response_code)) { http_response_code($response_code); } // Output headers foreach($this->headers as $header) { header($header); } // Save old URL Path $this->addFlash(self::FLASH_KEY_BACK, $_SERVER['REQUEST_URI']); // Output flashes foreach($this->flashes as $key=>$value) { Session::flash()->set($key, $value); } } }
RenderResponseクラスはResponseクラスから派生します。HTMLレンダリングを行うレスポンス用のクラスで、以下のメソッドを持ちます。addHeader()などのResponseクラスのメソッドも使用できます。
メソッド | 機能 |
---|---|
__construct(string $html=null) | RenderResponseの生成 |
setHtml(string $html=null):RenderResponse | HTMLテキストの設定 |
commit(int $response_code=null) | レスポンスの確定 |
/apricot/core/Foundation/Response
<?php namespace Core\Foundation\Response; /* * Rendered Response Class */ class RenderResponse extends \Core\Foundation\Response { /** * Html Data * @var string */ private $html=''; /** * Create RenderResponse * @param string $html * @param array $variables */ public function __construct(string $html=null) { $this->setHtml($html); } /** * Set Html * @param string $html * @return RenderResponse */ public function setHtml(string $html=null) : RenderResponse { if (isset($html)) $this->html = $html; return $this; } /** * commit * {@inheritDoc} * @see \Core\Foundation\Response::commit() */ public function commit(int $response_code=null) { // headersに'Content-type'がなければ出力する $matchs= preg_grep('/^content-type.*?:/i', $this->headers); if(empty($matchs)) { $this->addHeader("Content-type: text/html; charset=utf-8"); } parent::commit($response_code); // HTMLのレンダリング echo $this->html; flush(); } }
RedirectResponseクラスはResponseクラスから派生したリダイレクト用のクラスです。リダイレクトではフラッシュデータを使ってリダイレクト先のページにデータを送ることが多いので、フラッシュ用のメソッドが追加されています。RedirectResponseクラスは以下のメソッドを持ちます。addHeader()などのResponseクラスのメソッドも使用できます。
メソッド | 機能 |
---|---|
__construct(string $url) | RedirectResponseの生成 |
with(string $key, $value):RedirectResponse | フラッシュデータの追加 |
withInputs():RedirectResponse | 入力データをフラッシュに追加する |
withErrors(ErrorBag $errorBag):RedirectResponse | エラーバッグをフラッシュに追加する |
withOldErrors():RedirectResponse | 前回のエラーバッグを次のフラッシュに転送する |
以下は、レスポンスで使用するフラッシュデータのキーとその内容です。特に _old_inputs と errors はHTMLテンプレートで良く使用されます。
フラッシュキー | 内容 |
---|---|
_old_inputs | 前回の入力データ |
_old_path | 前回のURIパス |
errors | エラーバッグ |
/apricot/core/Foundation/Response
<?php namespace Core\Foundation\Response; use Core\Flash; use Core\Foundation\ErrorBag; /** * Redirected Response Class */ class RedirectResponse extends \Core\Foundation\Response { /** * Create RedirectResponse * @param string $url */ public function __construct(string $url) { $this->addHeader("Location: {$url}"); } /** * with * @param string $key * @param mixed $value * @return RedirectResponse */ public function with(string $key, $value):RedirectResponse { $this->addFlash($key, $value); return $this; } /** * withInputs * @return RedirectResponse */ public function withInputs():RedirectResponse { $this->addFlash(self::FLASH_KEY_OLD, \Core\Input::getRawData()); return $this; } /** * withErrors * @param \Core\Foundation\ErrorBag $message * @return RedirectResponse */ public function withErrors(ErrorBag $errorBag):RedirectResponse { $this->addFlash(self::FLASH_KEY_ERRORS, $errorBag); return $this; } /** * withOldErrors * @return RedirectResponse */ public function withOldErrors():RedirectResponse { if (Flash::has(self::FLASH_KEY_ERRORS)) { $this->addFlash(self::FLASH_KEY_ERRORS, Flash::get(self::FLASH_KEY_ERRORS)); } return $this; } }
レスポンス処理用のヘルパー関数を追加します。render()とredirect()はコントローラアクションで、その他はHTMLテンプレートでよく使われる関数です。
ヘルパー関数 | 機能 |
---|---|
render (string $view=null, array $variables=[]) :RenderResponse | RenderResponseの生成 テンプレート名とテンプレート変数を指定します |
redirect (string $url) :RedirectResponse | RedirectResponseの生成 リダイレクトURLを指定します |
old (string $key, $default = null) | キーを指定して前回の入力値を取得します |
back():string | 前回のURIを取得します |
errors():ErrorBag | 前回のエラーバッグを取得します |
/apricot/core/helpers
/** * render * @param string $view テンプレート名 * @param array $variables テンプレート変数のハッシュ * @return \Core\Foundation\Response\RenderResponse */ function render(string $view=null, array $variables=[]):Core\Foundation\Response\RenderResponse { $variables['errors'] = errors(); $html = isset($view) ? Core\View::run($view, $variables) : null; return new Core\Foundation\Response\RenderResponse($html); } /** * redirect * @param string $url URL * @return \Core\Foundation\Response\RedirectResponse */ function redirect(string $url):Core\Foundation\Response\RedirectResponse { return new Core\Foundation\Response\RedirectResponse($url); } /** * Get old request inputs * @param string $key * @param mixed $default * @return string */ function old(string $key, $default = null) { $old_inputs = flash(Core\Foundation\Response::FLASH_KEY_OLD); return isset($old_inputs) && array_key_exists($key, $old_inputs) ? $old_inputs[$key] : $default; } /** * Get old URL Path * @return string URL */ function back():string { if (array_key_exists('HTTP_REFERER', $_SERVER) && isset($_SERVER['HTTP_REFERER'])) { $url = '/'; $info = parse_url($_SERVER['HTTP_REFERER']); if (array_key_exists('path',$info)) $url = $info['path']; if (array_key_exists('query',$info)) $url .= '?'.$info['query']; if (array_key_exists('fragment',$info)) $url .= '#'.$info['fragment']; return $url; } else { return flash(Core\Foundation\Response::FLASH_KEY_BACK, '/'); } } /** * Get response errors * @return \Core\Foundation\ErrorBag */ function errors():Core\Foundation\ErrorBag { $errors = Core\Flash::has(Core\Foundation\Response::FLASH_KEY_ERRORS) ? flash(Core\Foundation\Response::FLASH_KEY_ERRORS) : new Core\Foundation\ErrorBag(); return $errors; }