beta

PHPライブラリ・AltoRouterでフレームワーク的なルーティングを実装する

フレームワークを使うほどじゃない小規模プロジェクトで、Laravel的ななルーティングを実装したくて、PHPライブラリ・AltoRouterを使ってみたのでまとめです。

公開日:2019年4月4日

やりたかったこと

非フレームワークでピュアなPHPでサイトを作る際に、Laravelのようにルーティングを設定ファイルに書くだけでルートとコントローラーをつないで処理する機能を実装したいと思い、ライブラリを探していました。

Route::get('hello/', 'App\Controllers\helloController@goodmorning');

こういうやつですね。

AltoRouterとは

PHPのルーティングライブラリです。

AltoRouter

Githubでソースコードが公開されていて、MITライセンスで自由に使うことができます。

AltoRouterをインストール

Composrerが楽なので、Composerでインストールしました。

composer requier altorouter/altorouter

ソースコードをGithubからダウンロードして、ソースコードをrequireしてもOKです。

dannyvankooten/AltoRouter | Github

ライブラリ本体は、ルートディレクトリのAltoRouter.phpです。このファイルを使いたいPHPファイルでrequireします。

require 'AltoRouter.php';

AltoRouterを使ってみる

ファイル構成

今回のテストでは、下記のようなファイル構成になります。

- index.php
- Core.php
- vendor
- .htaccess

AltoRouterはComposerでインストールしている前提とします。

まずは.htaccessを設定

AltoRouterは、すべてをindex.phpに集約してURLを変数化してマッチさせる方式になっているので、.htaccessの設定が必要です。Apache、Nginxで設定してもOKです。

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . index.php [L]

ルーティングの仕組みを書く

続いて、ルーティングの仕組みを書きます。

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

$router = new AltoRouter();

$router->map('GET|POST','/',
  'App\TopController::index',
  'home'
);

$match = $router->match();

if( is_array($match) && is_callable( $match['target'] ) ) {
  $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');
}

AltorouterでLaravel的なクラス名ルーティングをする方法

上記のコードはルート設定を含んでいますが、別ファイル化してもOKです。

注意したいのは、AltoRouterライブラリを読み込んだだけでは、何も動きません。AltoRouterがやっているのは、ルーティングのマッチ判定だけなので、

$match = $router->match();

で、リクエストに対してマッチ判定を行って「$match」に結果を格納してAltoRouterの役割としては終了です。

これだけではルーティングが出来ないので、

if( is_array($match) && is_callable( $match['target'] ) ) {
  $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');
}

で、コントローラー:メソッドを呼び出すようにします。

呼び出せるメソッドだったらcall_user_func_arrayでメソッドを実行して、ダメだったら404エラーを返すようにしてます。

index.phpの例

index.phpは先程のCore.phpを呼び出すだけでOKです。

<?PHP

reqire_once('Core.php');

これでAltoRouterでルーティングされるようになりました。

AltoRouterのルーティングの書き方

続いて、AltoRouterでのルーティングの書き方を見ていきます。

ルーティングの基本

もっともシンプルなのは、PHPファイルを読み込むケースですが、その場合は、

$router->map( 'GET', '/', function() {
    require __DIR__ . '/views/home.php';
});

これでOKです。

ルーティングの各変数を知る

各変数は、

$router->map(
  'GET|POST', # リクエストメソッド
  '/[a:siteCode]/',
  # マッチパターン
  'App\LogsController::writeLog',
 # アクション
  'writeLog'
 # alias(省略可能)
);

となっています。

アクション部分は、先程の例のようにそのままメソッドを展開させてもOKです。

最後の変数はaliasで、ここを設定しておくと、

$router->generate('home');

でURLを発行してくれます。このあたりもLaravelっぽいですね。

マッチパターンを知る

マッチパターンは、「パターン:変数名」のルールで書きます。

パターンは、下記のようになっています。

*                    // Match all request URIs
[i]                  // Match an integer
[i:id]               // Match an integer as 'id'
[a:action]           // Match alphanumeric characters as 'action'
[h:key]              // Match hexadecimal characters as 'key'
[:action]            // Match anything up to the next / or end of the URI as 'action'
[create|edit:action] // Match either 'create' or 'edit' as 'action'
[*]                  // Catch all (lazy, stops at the next trailing slash)
[*:trailing]         // Catch all as 'trailing' (lazy)
[**:trailing]        // Catch all (possessive - will match the rest of the URI)
.[:format]?          // Match an optional parameter 'format' - a / or . before the block is also optional


'i'  => '[0-9]++'
'a'  => '[0-9A-Za-z]++'
'h'  => '[0-9A-Fa-f]++'
'*'  => '.+?'
'**' => '.++'
''   => '[^/\.]++'

よく使うところでいうと、「a(英数字)」「i(数字)」でしょうか。正規表現も使えるので、比較的柔軟にマッチパターンを作れます。


PHPライブラリ・AltoRouterでフレームワーク的なルーティングを実装する方法をみてきました。概ねLaravelに近いルーティングが実装できたと思います。

ルーティングだけならピュアPHP + AltoRouterでも十分ですね。