超簡易ルーターを作成しました。

## 前置き

これ、本当に自分の良くない所だと思うのですが、Composerとかで入れるライブラリとかって分からないエラーが起きたり覚える事が多かったりで使うのが面倒なんですよね。
(なのでLaravelとかも中々踏み込めないでいるんですよね)

ということで自分用として簡易ルータを作りました()
とりあえずTinyRouterという名前にしておきました。

ソースコードは最後に載せますが、正直自分でもしっかり動くかわからないのでちゃんとしたサイトとかでは使わない方が良いです。

## これの特徴
- 本体容量が小さい & 1ファイル
- $_GETなどの変数をそのまま使える。
- **少しだけ**Node.jsのExpressに似てる
- できることが普通のルーターに比べて少ない
- 他のルーターに比べてしっかり作られてない
- 他のルーターとの互換性がない

## 使い方

```php
<?php
require_once 'TinyRouter.php';

$r = new TinyRouter();

$r->get('/', function() {
    echo "Hello, World!";
});

$r->get('/prof/*/*', function($array) {
    var_dump($array);
    // "/prof/hello/world" にアクセスされた場合
    // array(2) {
    //   [0]=>
    //   string(3) "hello"
    //   [1]=>
    //   string(3) "world"
    // }
}, 418);

$r->post('/sample', function() {
    redirect('/');
});

$r->all(function() {
    echo "404 not found";
}, 404);

```

`$r`のところは`$router`の略なので、好きな方に命名してください。

### 仕様
- まず先に言っておきますが、このルーターは`$r->get()`, `$r->post()`, `$r->all()`が実行されるとプログラムが終了します。これが嫌な場合[設定](#設定)で変更できます。<br>ただ、falseにする場合は無名関数の最後にexitを追加しないと、最後のall()も同時に実行されます。(これはSwitch分と少し似ています)
- `$r = new TinyRouter();` これでTinyRouterを読み込みます。
- `$r->get(引数1, 引数2)` 引数1にURLパス、第2引数に無名関数を置きます。<br>引数1のURLパスに当てはまった場合第2関数の中の無名関数が実行されます。<br>通常要りませんが、第2引数にステータスコードを入れると、そのステータスコードで表示します。
- `$r->get('/prof/*', function($array){})` 引数1の所にアスタリスク(*)を入れた場合、例えば`/prof/test`とアクセスすると、第2引数にある無名関数の第1引数($array[0])にtestと言う文字列が入ります。<br>因みに:idなどのように名前は付けられません。
- POSTに関しては `$r->post(引数1, 引数2)` という風にやれば良いです。
- `$r->all(無名関数)` すべてのリクエストを受け付けます。これを最初に書けば全て、最後に書けば上記のリクエストに当てはまらなかったものが受け付けられます。これは規定でステータスコードが404になるので、例のように第2引数に404と書かなくても良いです。

仕様の記載が少し雑だったかもしれませんが、プログラム自体はあまり難しくないと思います。

### 設定
最初の`$r = new TinyRouter();`の時点で第一引数にarrayを渡すことで設定ができます。
- `all_to_return_404` ⇒ all()を実行するときにHTTPステータスコード404を返します。 `規定: true`
- `responded_to_exit` ⇒ アクションを実行したときにプログラムを終了します。 `規定: true`
- `accepted_regex` ⇒ URL内のアスタリスクに適応する正規表現を指定します。 `規定: [a-zA-Z0-9\-_\.]+`

```php
$r = new TinyRouter([
  'responded_to_exit' => true,
]);
```

## ソースコード

一番上のredirectは要らない人は消しても良いです。

```php
<?php

function redirect(string $uri, int $http_response_code = 302) {
    header('Location: ' . $uri, true, $http_response_code);
}

class TinyRouter
{
    protected $uri_info;
    protected $config;

    function __construct(array $config = []) {
        $this->uri_info = parse_url($_SERVER['REQUEST_URI']);
        $this->config = array_merge([
            'all_to_return_404' => true,
            'accepted_regex' => '[a-zA-Z0-9\-_\.]+',
            'responded_to_exit' => true
        ], $config);
    }
    public function request(string $method = 'GET', string $uri = '/', $function, int $status_code = -1) {
        if($method === '*') {
            if($status_code !== -1) {
                http_response_code($status_code);
            }
            if($this->config['responded_to_exit'] === true) {
                return $function() . exit;
            } else {
                return $function();
            }
        }
        if($_SERVER["REQUEST_METHOD"] !== strtoupper($method)) {
            return false;
        }
        if(strpos($uri, '*') !== false) {
            $pattern = '/^' . preg_quote($uri, '/') . '$/';
            $pattern = str_replace('\*', '(' . $this->config['accepted_regex'] . ')', $pattern);
            if(preg_match($pattern, $this->uri_info['path'], $matches)) {
                if($status_code !== -1) {
                    http_response_code($status_code);
                }
                array_shift($matches);
                if($this->config['responded_to_exit'] === true) {
                    return $function($matches) . exit;
                } else {
                    return $function($matches);
                }
            }
        } else {
            if($uri === $this->uri_info['path']) {
                if($status_code !== -1) {
                    http_response_code($status_code);
                }
                if($this->config['responded_to_exit'] === true) {
                    return $function() . exit;
                } else {
                    return $function();
                }
            }    
        }
        return false;
    }
    public function get(string $uri, $function, int $status_code = -1) {
        return $this->request('GET', $uri, $function, $status_code);
    }
    public function post(string $uri, $function, int $status_code = -1) {
        return $this->request('POST', $uri, $function, $status_code);
    }
    public function all($function, int $status_code = -1) {
        if($this->config['all_to_return_404'] === true) {
            $status_code = 404;
        }
        return $this->request('*', '', $function, $status_code);
    }
}
```

## 最後に
(そもそもLaravelをちゃんと勉強しろっていう話ですが)このプログラムでダメな部分などありましたら、コメントしていただけると幸いです。