RFC6570というRFCがあります。
http://tools.ietf.org/html/rfc6570
簡単に言うと、
『 http://example.com/{controller}/{action} 』を『 http://example.com/hoge/fuga 』に展開できたら楽じゃね、という最近のフレームワークでよく見かけるルーティングをRFCに仕上げたものです。
フレームワークならだいたい最初から付属しているし、自力で作るにしても簡単なのならSmartyなりZend\Uri\Uriなりで十分ですが、RFC6570に沿ったエクステンションがあったので試してみます。
使用したバージョンは1.0です。
<?php
// 変換テーブル
$table = [
'var' => 'value',
'hello' => 'Hello World!',
'path' => '/foo/bar',
'empty' => '',
'x' => '1024',
'y' => '768',
'list' => ['red', 'green', 'blue'],
'keys' => ['semi'=>';','dot'=>'.','comma'=>','],
];
// レベル1
$level1 = [
'{var}' => 'value',
'{hello}' => 'Hello%20World%21',
];
// レベル2
$level2 = [
'{+var}' => 'value',
'{+hello}' => 'Hello%20World!',
'{+path}/here' => '/foo/bar/here',
'here?ref={+path}'=>'here?ref=/foo/bar',
'X{#var}'=>'X#value',
'X{#hello}'=>'X#Hello%20World!',
];
// レベル3
$level3 = [
'map?{x,y}' => 'map?1024,768',
'{x,hello,y}' => '1024,Hello%20World%21,768',
'{+x,hello,y}' => '1024,Hello%20World!,768',
'{+path,x}/here' => '/foo/bar,1024/here',
'{#x,hello,y}' => '#1024,Hello%20World!,768',
'{#path,x}/here' => '#/foo/bar,1024/here',
'X{.var}' => 'X.value',
'X{.x,y}' => 'X.1024.768',
'{/var}' => '/value',
'{/var,x}/here' => '/value/1024/here',
'{;x,y}' => ';x=1024;y=768',
'{;x,y,empty}' => ';x=1024;y=768;empty',
'{?x,y}' => '?x=1024&y=768',
'{?x,y,empty}' => '?x=1024&y=768&empty=',
'?fixed=yes{&x}' => '?fixed=yes&x=1024',
'{&x,y,empty}' => '&x=1024&y=768&empty=',
];
// レベル4
$level4 = [
'{var:3}' => 'val',
'{var:30}' => 'value',
'{list}' => 'red,green,blue',
'{list*}' => 'red,green,blue',
'{keys}' => 'semi,%3B,dot,.,comma,%2C',
'{keys*}' => 'semi=%3B,dot=.,comma=%2C',
'{+path:6}/here' => '/foo/b/here',
'{+list}' => 'red,green,blue',
'{+list*}' => 'red,green,blue',
'{+keys}' => 'semi,;,dot,.,comma,,',
'{+keys*}' => 'semi=;,dot=.,comma=,',
'{#path:6}/here' => '#/foo/b/here',
'{#list}' => '#red,green,blue',
'{#list*}' => '#red,green,blue',
'{#keys}' => '#semi,;,dot,.,comma,,',
'{#keys*}' => '#semi=;,dot=.,comma=,',
'X{.var:3}' => 'X.val',
'X{.list}' => 'X.red,green,blue',
'X{.list*}' => 'X.red.green.blue',
'X{.keys}' => 'X.semi,%3B,dot,.,comma,%2C',
'X{.keys*}' => 'X.semi=%3B.dot=..comma=%2C',
'{/var:1,var}' => '/v/value',
'{/list}' => '/red,green,blue',
'{/list*}' => '/red/green/blue',
'{/list*,path:4}' => '/red/green/blue/%2Ffoo',
'{/keys}' => '/semi,%3B,dot,.,comma,%2C',
'{/keys*}' => '/semi=%3B/dot=./comma=%2C',
'{;hello:5}' => ';hello=Hello',
'{;list}' => ';list=red,green,blue',
'{;list*}' => ';list=red;list=green;list=blue',
'{;keys}' => ';keys=semi,%3B,dot,.,comma,%2C',
'{;keys*}' => ';semi=%3B;dot=.;comma=%2C',
'{?var:3}' => '?var=val',
'{?list}' => '?list=red,green,blue',
'{?list*}' => '?list=red&list=green&list=blue',
'{?keys}' => '?keys=semi,%3B,dot,.,comma,%2C',
'{?keys*}' => '?semi=%3B&dot=.&comma=%2C',
'{&var:3}' => '&var=val',
'{&list}' => '&list=red,green,blue',
'{&list*}' => '&list=red&list=green&list=blue',
'{&keys}' => '&keys=semi,%3B,dot,.,comma,%2C',
'{&keys*}' => '&semi=%3B&dot=.&comma=%2C',
];
// 確認
$level = array_merge($level1, $level2, $level3, $level4);
foreach($level as $key=>$val){
// 変換
$template = uri_template($key, $table);
if($template !== $val){
print('えらー');
}
}
エラーは出ません。
RFC6570には4段階のレベルがありますが、uri_templateは全レベル対応しています。
完全にRFC6570に従ったURIを出力しました。
これでURIを組み立てるのが便利に…なるのか?
普通にrawurlencodeとか使って作った方が早い気がしないでもない。