Napisałem już kontroler PHP, ale przepisuję mój kod, więc mogę mieć trasy JSON typu routera szkieletowego, które odwzorowują wzorce URI na kombinacje PHP Class :: method, lub bezpośrednio do dokumentów HTML, które są następnie dostarczane do klienta, tak jak poniżej:Rdzeń podobny do routera z dynamicznym regexem w PHP
{
"/home" : "index.html",
"/podcasts": "podcasts.html",
"/podcasts/:param1/:param2": "SomeClass::someMethod"
}
Backbone dynamicznie tworzy regexes dopasować trasy przed adresów URL. Wziąłem zajrzeć do kodu szkieletowej, a ja ekstrakcji następujący kod (to nieco zmodyfikowany):
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 + '$');
}
Kiedy mijam trasy jak /podcasts/:param1/:param2
, do powyższego kodu, otrzymuję /^\/podcasts\/([^\/]+)\/([^\/]+)$/
. Próbowałem napisać funkcję PHP, aby uzyskać dokładnie to samo wyrażenie regularne. Próbowałem:
$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);
moje wyjście jest:
/^\/podcasts\/([^\/]+)\/([^\/]+)$/ // The expected pattern
/^/podcasts/([^\/]+)/([^\/]+)$/ // echo "{$pattern}\n";
Array // print_r($matches);
(
)
Dlaczego wyjście regex inaczej? Potrafię sobie poradzić z resztą procesu mapowania i wszystkim, ale nie wiem, jak uzyskać dokładnie to samo wyrażenie w PHP, co w JavaScript. Jakieś sugestie?
To było zbyt frustrujące, więc kolega pomógł mi napisać bardzo wygodną funkcję nodeJs, która zwraca to wyrażenie regularne za pośrednictwem interfejsu CLI. Jeśli znajdę sposób na zrobienie tego w PHP, na pewno opublikuję poprawną odpowiedź. :) –
Łatwe rozwiązanie: użyj ~ do wytyczenia wyrażenia regularnego - tj. ~ Wzorca ~ zamiast/wzorca /. W ten sposób nie musisz uciekać od/znaków. Ułatwia to również czytanie wyrażenia regularnego. – ajshort