Добрый день.
Пишу простую маршрутизацию на регулярных выражениях, прошу помощи.
Про велосипеды говорить не нужно - пишу в целях обучения и , возможно, для своих проектов.
Имеются наработки:
<?php
class Route
{
private $map = null;
private $patterns = [
'{all}',
'{number}',
'{char}'
];
private $replacements = [
'(.+)',
'([0-9]+)',
'([a-zA-Z]+)'
];
public function add($method, $string, $action, $vars = null){
$method = strtoupper($method);
$string = strtolower($string);
if(!strstr($string,'{')){
$this->map[$method]['static'][$string] =[
'action' => $action
];
return;
}
$replaced = str_replace($this->patterns, $this->replacements, $string);
$replaced = '#^'.$replaced.'$#';
$this->map[$method]['regexp'][$replaced] = [
'action' => $action
];
if($vars){
$vars = (array)$vars;
$this->map[$method]['regexp'][$replaced]['vars'] = $vars;
}
}
public function start(){
$url = explode('?',urldecode($_SERVER['REQUEST_URI']))[0];
$method = $_SERVER['REQUEST_METHOD'];
// in static
if(isset($this->map[$method]['static'][$url])){
return $this->load($this->map[$method]['static'][$url]);
}
// in regex
foreach ($this->map[$method]['regexp'] as $pattern => $data) {
if(!preg_match($pattern, $url,$match)){
continue;
}
return $this->load($data,$match);
}
// 404 - controller/action
die('not founded');
}
private function load($data, $match = null){
/*
$data - массив с controler/actions + возможно имена переменных
*/
}
}
$route = new Route();
$route->add('GET', '/news/{number}', 'controller/action', 'id');
$route->add('POST', '/news/{number}_{all}_{sdcsdc}', 'controller/action', '[id,name]');
$route->add('GET', '/news', 'News');
$route->add('GET', '/', 'home');
$route->start();
Массив адресов имеет структуру [Метод(POST|GET)][ТИП(статичный|REGEXP)].
При добавлении правила проверяю наличие в строке символа "}", если символа нет, то добавляю статичный маршрут, если есть, то подставляю регулярные выражения через str_replace() (число|строка|все), подразумевается, что неправильный маршрут не буду добавлять.
При добавлении правила с регулярным выражением можно дать имена переменным - '1|2 добавление'.
При старте, ищу сначала через isset() в статике, потом, если не нашел - через preg_match().
Вопросы:
На сколько рабочим является текущий вариант?
Планирую добавить кешрование карты маршрутов ($map) и готовых адресов.
При инициализации добавить загрузку из файла, проверенные regex маршруты дописывать в еще один файл и проверять вначале в нем, либо в тот-же $map, в static, какой из вариантов предпочтительней?
Есть ли разница в чем хранить - json или serialize?
Насколько будет производительный isset()?
Что еще можно добавить, в какую сторону смотреть?
Буду благодарен за любую полезную информацию.