6

すでにPHPコントローラーを作成しましたが、コードを書き直して、URIパターンをPHP Class :: methodの組み合わせに、または直接HTMLドキュメントにマップしてクライアントに配信するバックボーンルーターのようなJSONルートを作成できるようにしています。 、 そのようです:

{
  "/home" : "index.html",
  "/podcasts": "podcasts.html",
  "/podcasts/:param1/:param2": "SomeClass::someMethod"
}

バックボーンは、URLに対してルートを照合するために正規表現を動的に作成します。バックボーンコードを調べて、次のコードを抽出しました(少し変更されています)。

function _routeToRegExp (route) {
  var optionalParam = /\((.*?)\)/g;
  var namedParam    = /(\(\?)?:\w+/g;
  var splatParam    = /\*\w+/g;
  var escapeRegExp  = /[\-{}\[\]+?.,\\\^$|#\s]/g;
  route = route.replace(escapeRegExp, '\\$&')
               .replace(optionalParam, '(?:$1)?')
               .replace(namedParam, function(match, optional){
                 return optional ? match : '([^\/]+)';
               })
              .replace(splatParam, '(.*?)');
  return new RegExp('^' + route + '$');
}

のようなルートを/podcasts/:param1/:param2上記のコードに渡すと、が得られ/^\/podcasts\/([^\/]+)\/([^\/]+)$/ます。まったく同じ正規表現を取得するためにPHP関数を作成しようとしていました。私は試した:

$route = '/podcasts/:param1/:param2';
$a = preg_replace('/[\-{}\[\]+?.,\\\^$|#\s]/', '\\$&', $route); // escapeRegExp
$b = preg_replace('/\((.*?)\)/', '(?:$1)?', $a);                // optionalParam
$c = preg_replace('/(\(\?)?:\w+/', '([^\/]+)', $b);             // namedParam
$d = preg_replace('/\*\w+/', '(.*?)', $c);                      // splatParam
$pattern = "/^{$d}$/";
echo "/^\/podcasts\/([^\/]+)\/([^\/]+)$/\n";
echo "{$pattern}\n";
$matches = array();
preg_match_all($pattern, '/podcasts/param1/param2', $matches);
print_r($matches);

私の出力は次のとおりです。

/^\/podcasts\/([^\/]+)\/([^\/]+)$/    // The expected pattern
/^/podcasts/([^\/]+)/([^\/]+)$/       // echo "{$pattern}\n";
Array                                 // print_r($matches);
(
)

正規表現の出力が異なるのはなぜですか?残りのマッピングプロセスとすべてを処理できますが、PHPでJavascriptとまったく同じ正規表現を取得する方法がわかりません。助言がありますか?

4

1 に答える 1

2

JS バージョンは実際には / 文字をエスケープしません。それは PHP バージョンと同じ文字列表現を生成します が 、おそらくそれがあなたをつまずか/podcasts/([^/]+)/([^/]+)せたのでしょう。:console.log_routeToRegExp

//Firefox output
RegExp /^\/podcasts\/([^\/]+)\/([^\/]+)$/ 

デモについては、 http://jsfiddle.net/w6zP2/を参照してください。

@ajshort がコメントで指摘したことと Backbone が行うことは同じ解決策です。 / エスケープをスキップし、別の構文を使用します。バックボーンは、正規表現コンストラクターへの明示的な呼び出しでそれを行いnew RegExp('^' + route + '$')ます。$pattern = "~^{$d}$~";

そして、期待どおりに動作するように見える PHP Fiddle http://phpfiddle.org/main/code/4de-jf3

Javascript$&では、置換文字列に一致する部分文字列1が挿入されますが、PHP 2ではそうではないことに注意してください。escapeRegExp を変更する必要があり、次のようになります。

$a = preg_replace('/[\-{}\[\]+?.,\\\^$|#~\s]/', '\\\\$0', $route);

これにより、更新されたコードが得られます。

$a = preg_replace('/[\-{}\[\]+?.,\\\^$|#~\s]/', '\\\\$0', $route); // escapeRegExp
$b = preg_replace('/\((.*?)\)/', '(?:$1)?', $a);                // optionalParam
$c = preg_replace('/(\(\?)?:\w+/', '([^\/]+)', $b);             // namedParam
$d = preg_replace('/\*\w+/', '(.*?)', $c);                      // splatParam
$pattern = "~^{$d}$~";

echo "/^\/podcasts\/([^\/]+)\/([^\/]+)$/\n";
echo "{$pattern}\n";
$matches = array();
preg_match_all($pattern, '/podcasts/param1/param2', $matches);
print_r($matches);

1 string.replace文字列をパラメーターとして指定するを参照してください。 2 preg_replaceで置換を参照してください。

于 2013-02-01T05:00:28.360 に答える