PHP --- フレームワークを利用しないでToDoアプリ作成(1)

PHPにはCakePHPやLaravelなどのフレームワークがたくさん存在します。

このシリーズでは、これらのフレームワークを利用せず、一からToDoアプリを作成してみたいと思います。

本実装はローレベルの挙動を理解するためのものとして、実際のアプリ作成ではフレームワークを利用することをお勧めします。

本実装は下記の書籍「パーフェクトPHP」を大いに参照しています。
https://www.amazon.co.jp/dp/4774144371

今回の作成物

下記のindex.phpとview.phpを準備してindex.phpにアクセスすると、Hello worldと表示されるページが返ってきます。

index.php

<?php
$content = render('view.php', [ 'name' => 'world' ]);
Response::ok($content)->send();


view.php

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>Hello</title>
</head>
<body>

<p>Hello <?php safeEcho($name) ?></p>

</body>
</html>

f:id:any-programming:20180602181736p:plain

Responseクラス

クライアントにデータを返す役割をはたすクラスになります。

データをセットしてsend関数を呼ぶことでクライアントにデータを送付します。

OKやRedirectなど、よく使うレスポンスを作成する関数をいくつか定義してあります。

<?php
class Response {
    public $statusCode;
    public $statusText;
    public $httpHeaders;
    public $content;
    function __construct(int $statusCode, string $statusText, array $httpHeaders, string $content) {
        $this->statusCode  = $statusCode;
        $this->statusText  = $statusText;
        $this->httpHeaders = $httpHeaders;
        $this->content     = $content;
    }
    function send() : void {
        header("HTTP/1.1 {$this->statusCode} {$this->statusText}");
        foreach ($this->httpHeaders as $name => $value) {
            header("{$name}: {$value}");
        }
        echo $this->content;
    }

    public static function ok(string $content) : Response {
        return new Response(200, 'OK', [], $content);
    }
    public static function redirect(string $pathInfo) : Response {
        $protocol = ($_SERVER['HTTPS'] ?? '') === 'on' ? 'https://' : 'http://';
        $url = $protocol . $_SERVER['HTTP_HOST'] . $pathInfo;
        return new Response(302, 'Found', [ 'Location' => $url ], '');
    }
    public static function badRequest(string $content) : Response {
        return new Response(400, 'Bad Request', [], $content);
    }
    public static function forbidden(string $content) : Response {
        return new Response(403, 'Forbidden', [], $content);
    }
    public static function notFound(string $content) : Response {
        return new Response(404, 'Not Found', [], $content);
    }
    public static function internalServerError(string $content) : Response {
        return new Response(500, 'Internal Server Error', [], $content);
    }
}


render関数

表示用のphp(今回の例だとview.php)を、phpの部分を処理して結果をstringとして取得する関数となります。

extract関数で、辞書データを変数定義に変換します。(今回の例だと、[ 'name' => 'world' ] が $name = 'world' に展開されます。またその他の変数が邪魔をしないよう、アンダースコア始まりにしてあります。)

ob_startとob_get_cleanで囲むことにより、phpの出力を内部バッファに溜めて文字列で取得することができます。

勝手にバッファの内容が送信されないよう、ob_implicit_flushをoffにしてあります。

<?php
function render(string $_file, array $_args) : string {
    extract($_args);

    ob_start();
    ob_implicit_flush(0);
    require $_file;
    return ob_get_clean();
}


safeEcho関数

htmlの特殊文字として扱われないよう、エスケープを行う関数です。

もともとhtmlspecialcharsという関数が用意されており、シングルクオートとダブルクオートもエスケープするようにしてあります。

<?php
function safeEcho($x) : void {
    echo htmlspecialchars($x, ENT_QUOTES);
}