Автор оригинала: David Wong.
Веб-сайт:Маршрутизатор быстрых запросов для PHP
`
php
class PregRoute
{
const NOT_FOUND = 404;
const FOUND = 200;
/** ~^/user/([^/]+)/(\d+)$~
* ~^/user/(\d+)$~
* ~^/user/([^/]+)$~
*@ var string single regular
*/
protected $single_regex = '~^/user/([^/]+)/(\d+)$~';
/**Location based matching
*@ var string multiple route matching rules
*/
protected $combined_position_regex = "
~^(?:
/user/([^/]+)/(\d+)
| /user/(\d+)
| /user/([^/]+)
)$~x";
/**Location matching data
* @var array
*/
protected $route_data_position = [
1 => ['handler0', ['name', 'id']], # /user/tom/1 regex=> /user/([^/]+)/(\d+)
3 => ['handler1', ['id']], # /user/1 regex=> /user/(\d+)
4 => ['handler2', ['name']], # /user/tom regex=> /user/([^/]+)
];
/**Count based matching
*@ var string multiple route matching rules
*/
protected $combined_count_regex = "
~^(?|
/user/([^/]+)/(\d+)
| /user/(\d+)()()
| /user/([^/]+)()()()
)$~x";
/**Count based matching,只修改 ?:
*@ result: you can reset the group number by changing?: to? |, but
* | /user/(\d+)
*| / user / ([^ /] +) has the same count. Use () to fill in the number. You can also use other methods, such as
* /user/(\d+)
* /user/([^/]+)
* @var string
*/
protected $combined_count_regex2 = "
~^(?|
/user/([^/]+)/(\d+)
| /user/(\d+)
| /user/([^/]+)
)$~x";
/**Count match data
* @var array
*/
protected $route_data_count = [
3 => ['handler0', ['name', 'id']], # /user/tom/1 regex=> /user/([^/]+)/(\d+)
4 => ['handler1', ['id']], # /user/1 regex=> /user/(\d+)
5 => ['handler2', ['name']], # /user/tom regex=> /user/([^/]+)
];
/**Block regular expression
* @var array
*/
protected $combined_count_regexes = [];
/**Block regular expression数据
* @var array
*/
protected $route_data_counts = [];
/**Scheduling route based on location
* @param $url
*@ way non block based on group position
*@ result provides good performance with a single placeholder
*Too many placeholders, in the worst case (last route match), performance drops to more than twice slower than the normal method
* @return array
*/
public function dispatchPosition($url)
{
if(!preg_match($this->combined_position_regex,$url,$matches)) {
return [self::NOT_FOUND];
}
//$I after finding the first non empty offset and finding the relevant data
//You can populate the placeholder variable by continuing through the $matches array and pairing the value with the variable name.
for($i = 1; '' === $matches[$i]; ++$i);
list($handler, $varNames) = $this->route_data_position[$i];
$vars = [];
foreach ($varNames as $varName) {
$vars[$varName] = $matches[$i++];
}
return [self::FOUND, $handler, $vars];
}
//++++++++++++++++++++++++++++++++++++++++
//Group number reset:
//PCRE regex syntax:
//(? |...) is a non capture group type.
//(?: the difference between and is that (? | the latter will reset the group number in each branch it contains
//++++++++++++++++++++++++++++++++++++++++
/**Scheduling routing based on count
* @param $url
* @return array
*/
public function dispatchCount($url)
{
if(!preg_match($this->combined_count_regex,$url,$matches)) {
return [self::NOT_FOUND];
}
list($handler, $varNames) = $this->route_data_count[count($matches)];
$vars = [];
$i = 0;
foreach ($varNames as $varName) {
$vars[$varName] = $matches[++$i];
}
return [self::FOUND, $handler, $vars];
}
/**Scheduling routing based on count,非()占位
* @param $url
* @return array
*/
public function dispatchCount2($url)
{
if(!preg_match($this->combined_count_regex2,$url,$matches)) {
return [self::NOT_FOUND];
}
var_dump($matches);
}
/**Block regular expression调度
* @param $url
* @return array
*/
public function dispatchBlock($url)
{
foreach ($this->combined_count_regexes as $i => $regex) {
if (!preg_match($regex, $url, $matches)) {
continue;
}
list($handler, $varNames) = $this->route_data_counts[$i][count($matches)];
$vars = [];
$i = 0;
foreach ($varNames as $varName) {
$vars[$varName] = $matches[++$i];
}
return [self::FOUND, $handler, $vars];
}
}
//+++++++++++++++++++++++++++++++++++++++++
//The combined regular expression method is very effective for a small number of regular expressions,
//However, it is not the best choice if many regular expressions are involved, and it is disastrous if there are multiple capture groups for each rule.
//You can improve performance by combining only blocks of about ten expressions.
//This can not only improve the performance on the whole, but also solve the problem that the performance is especially poor in many groups.
//Once you start using chunking, the alternative based on group counting doesn't make much difference.
//When there are fewer capture groups, the situation is slightly worse, while many groups are slightly better. Especially for routes, each route usually involves multiple placeholders, and the group count based method seems preferable.
//On the other hand, for lexical analysis, each tag usually uses only one capture group, so the location-based approach will win.
//+++++++++++++++++++++++++++++++++++++++++
}
$testClass = new PregRoute();
$url = '/user/tom'; #/user/1 | /user/tom/1
$dispatchPosition = $testClass->dispatchPosition($url);
$dispatchCount = $testClass->dispatchCount($url);
var_dump($dispatchPosition);
var_dump($dispatchCount); `
Оригинал: “https://developpaper.com/fastroute-test-demo/”