2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

phpのroutingライブラリAltorouterの紹介

Last updated at Posted at 2021-07-23

モチベーション

webアプリケーションのよくあるパターンは、index.phpで処理を受けたらURIに応じてルーティングしてリクエストされた処理を実行するというものですが、フレームワークを使っていないアプリケーションの場合、URIがそのまま、実行されるスクリプトのファイル名になっているケースがあります(hoge.com/login.phpみたいな感じ)。こういったアプリケーションの保守をしやすくするためにルーティングを入れたかったのでAltoRouterというライブラリを(超基本的な使い方だけですが)検証してみました。

Altorouterとは

klein.phpに影響を受けたルーティングライブラリだそうです。

公式ドキュメント

類似ライブラリとの比較

サンプルリポジトリ

導入

composerで普通に入れる

composer require altorouter/altorouter

実装例

単純な例で検証してみます。

.
├── composer.json
├── composer.lock
├── api
│   └── user.php // 単純なスクリプトを置いてみる
├── public
│   └── index.php // ここにルーティング定義を書く
└── src
    └── Http
        └── Handler
            └── Welcome.php //controllerぽい感じでクラスを置いてみる

index.phpの例

<?php

declare(strict_types=1);

require_once __DIR__ . '/../vendor/autoload.php';

$router = new AltoRouter();

// スクリプトを直で呼び出す
$router->map('GET|POST|PATCH|DELETE', '/user', function () {
    require_once __DIR__ . '/../api/user.php';
});

// laravelっぽくクラスとメソッドを指定する
$router->map('GET', '/', 'isanasan\Router\Http\Handler\Welcome::get', 'welcome');

$match = $router->match();

if ($match !== false) {
    if (is_callable($match['target'])) {
        $match['target']();
    } else {
        $params = explode("::", $match['target']);
        $action = new $params[0]();
        call_user_func_array(array($action, $params[1]), $match['params']);
    }
} else {
    header($_SERVER["SERVER_PROTOCOL"] . ' 404 Not Found');
}

src/Http/Handlerの中身

<?php

namespace isanasan\Router\Http\Handler;

class Welcome
{
    public function get()
    {
        echo 'welcome';
    }
}

api/user.phpの中身

<?php

switch ($_SERVER['REQUEST_METHOD']) {
    case 'GET':
        $response = 'isana';
        echo $response;
        break;
    case 'POST':
    case 'PATCH':
    case 'DELETE':
}

以下のコマンドでビルトインサーバを実行します。
php -S 127.0.0.1:3939 public/index.php -t public

http://127.0.0.1:3939/へアクセス
image

http://127.0.0.1:3939/userへアクセス
image

このようにアクセスしたURIに応じて処理をルーティングできました。今回は非常に簡単な例しか試していませんが、router->map()の第二引数を/users/[i:id]/のような形にすることでより実用的なルーティングが設定できます。

既存プロジェクトに入れて使う場合は、既に動いているページをrequireで読み込むことで対応し、これから新しく追加していく機能はコントローラっぽい使い方でルーティングすると良いのではないでしょうか。

ハマりポイント

laravelっぽくルーティングする際にis_callable($match['target'])で判定しようとしても$router->map()の第三引数はただの文字列にしか過ぎないのでcall_user_func()で呼べませんでした。

余談

検証はビルトインサーバーを使いましたがmod_phpなら.htaccessを置きます。

.htaccessの例

<IfModule mod_rewrite.c>
    # negotiation拡張を無効化
    <IfModule mod_negotiation.c>
            Options -MultiViews -Indexes
    </IfModule>
    # phpファイルへの直接アクセスを禁じる
    <Files ~ "(\.php)$">
        deny from all
    </Files>
    # index.phpへのアクセスを許可
    <Files ~ "^(index\.php)">
        allow from all
    </Files>

    # public/index.phpへリライト
    RewriteEngine on
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule . public/index.php [L]
</IfModule>

参考

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?