Skip to content

Commit 750817e

Browse files
committed
Merge pull request #32 from skipperbent/development
[FEATURE] Optimised route matching, added optional parameters.
2 parents 5c36e9c + 3b49548 commit 750817e

File tree

4 files changed

+78
-77
lines changed

4 files changed

+78
-77
lines changed

README.md

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,12 @@ Add the latest version pf Simple PHP Router to your ```composer.json```
2828
- Namespaces.
2929
- Route prefixes.
3030
- CSRF protection.
31+
- Optional parameters
3132

3233
### Features currently "in-the-works"
3334

3435
- Global Constraints
35-
- Sub-Domain Routing
36-
- Optional parameters
36+
- Sub-domain routing
3737

3838
## Initialising the router
3939

@@ -74,16 +74,18 @@ SimpleRouter::group(['prefix' => 'v1', 'middleware' => '\MyWebsite\Middleware\So
7474

7575
SimpleRouter::group(['prefix' => 'services'], function() {
7676

77-
SimpleRouter::get('/answers/{id}', 'ControllerAnswers@show')
78-
->where(['id' => '[0-9]+');
77+
SimpleRouter::get('/answers/{id}', 'ControllerAnswers@show')->where(['id' => '[0-9]+');
78+
79+
// Optional parameter
80+
SimpleRouter::get('/answers/{id?}', 'ControllerAnswers@show');
7981

8082
/**
8183
* This example will route url when matching the regular expression to the method.
8284
* For example route: /ajax/music/world -> ControllerAjax@process (parameter: music/world)
8385
*/
8486
SimpleRouter::all('/ajax', 'ControllerAjax@process')->match('ajax\\/([A-Za-z0-9\\/]+)');
8587

86-
// Resetful resource
88+
// Restful resource
8789
SimpleRouter::resource('/rest', 'ControllerRessource');
8890

8991
// Load the entire controller (where url matches method names - getIndex(), postIndex() etc)
@@ -251,7 +253,7 @@ The router can be easily extended to customize your needs.
251253

252254
## The MIT License (MIT)
253255

254-
Copyright (c) 2015 Simon Sessing� / simple-php-router
256+
Copyright (c) 2015 Simon Sessingø / simple-php-router
255257

256258
Permission is hereby granted, free of charge, to any person obtaining a copy
257259
of this software and associated documentation files (the "Software"), to deal

src/Pecee/SimpleRouter/RouterBase.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ protected function processUrl($route, $method = null, $parameters = null, $getPa
224224
$i = 0;
225225
foreach($params as $param => $value) {
226226
$value = (isset($parameters[$param])) ? $parameters[$param] : $value;
227-
$url = str_ireplace('{' . $param. '}', $value, $url);
227+
$url = str_ireplace(array('{' . $param. '}', '{' . $param. '?}'), $value, $url);
228228
$i++;
229229
}
230230
} else {

src/Pecee/SimpleRouter/RouterRoute.php

Lines changed: 68 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -18,98 +18,93 @@ public function __construct($url, $callback) {
1818
$this->settings['aliases'] = array();
1919
}
2020

21-
protected function parseParameters($url, $multiple = false, $regex = self::PARAMETERS_REGEX_MATCH) {
22-
$url = rtrim($url, '/');
23-
$parameters = array();
21+
public function matchRoute(Request $request) {
2422

25-
if($multiple) {
26-
preg_match_all('/'.$regex.'/is', $url, $parameters);
27-
} else {
28-
preg_match('/'.$regex.'/is', $url, $parameters);
29-
}
23+
$url = parse_url($request->getUri());
24+
$url = rtrim($url['path'], '/') . '/';
3025

31-
if(isset($parameters[1]) && count($parameters[1]) > 0) {
32-
return $parameters[1];
26+
// Match on custom defined regular expression
27+
if($this->regexMatch) {
28+
$parameters = array();
29+
if(preg_match('/'.$this->regexMatch.'/is', $url, $parameters)) {
30+
$this->parameters = $parameters[0];
31+
return $this;
32+
}
3333
}
3434

35-
return null;
36-
}
37-
38-
public function matchRoute(Request $request) {
39-
40-
// Check if request method is allowed
41-
42-
$url = parse_url($request->getUri());
43-
$url = $url['path'];
35+
// Make regular expression based on route
4436

4537
$route = rtrim($this->url, '/') . '/';
4638

47-
$routeMatch = preg_replace('/\/{0,1}'.self::PARAMETERS_REGEX_MATCH.'\/{0,1}/is', '', $route);
48-
49-
$tmp = explode('/', $route);
50-
$tmp2 = explode('/', $url);
39+
$parameterNames = array();
40+
$regex = '';
41+
$lastCharacter = '';
42+
$isParameter = false;
43+
$parameter = '';
5144

52-
// Check if url parameter count matches
53-
if(stripos($url, $routeMatch) === 0 || count($tmp) === count($tmp2)) {
45+
for($i = 0; $i < strlen($route); $i++) {
5446

55-
$matches = true;
47+
$character = $route[$i];
5648

57-
if($this->regexMatch) {
58-
$parameters = $this->parseParameters($url, true, $this->regexMatch);
49+
// Skip "/" if we are at the end of a parameter
50+
if($lastCharacter === '}' && $character === '/') {
51+
$lastCharacter = $character;
52+
continue;
53+
}
5954

60-
// If regex doesn't match, make sure to return an array
61-
if(!is_array($parameters)) {
62-
$parameters = array();
55+
if($character === '{') {
56+
// Remove "/" and "\" from regex
57+
if(substr($regex, strlen($regex)-1) === '/') {
58+
$regex = substr($regex, 0, strlen($regex) - 2);
6359
}
6460

65-
} else {
66-
67-
$matches = (count(explode('/', rtrim($url, '/'))) == count(explode('/', rtrim($route, '/'))));
68-
69-
$url = explode('/', $url);
70-
$route = explode('/', rtrim($route, '/'));
71-
72-
$parameters = array();
61+
$isParameter = true;
62+
} elseif($isParameter && $character === '}') {
63+
// Check for optional parameter
64+
if($lastCharacter === '?') {
65+
$parameter = substr($parameter, 0, strlen($parameter)-1);
66+
$regex .= '(?:(?:\/(?P<'.$parameter.'>[0-9]*?)){0,1}\\/)';
67+
} else {
68+
// Use custom parameter regex if it exists
69+
$parameterRegex = '[0-9]*?';
70+
71+
if(is_array($this->parametersRegex) && isset($this->parametersRegex[$parameter])) {
72+
$parameterRegex = $this->parametersRegex[$parameter];
73+
}
7374

74-
// Check if url matches
75-
foreach ($route as $i => $path) {
76-
$parameter = $this->parseParameters($path, false);
75+
$regex .= '(?:\\/(?P<' . $parameter . '>'. $parameterRegex .')\\/)';
76+
}
77+
$parameterNames[] = $parameter;
78+
$parameter = '';
79+
$isParameter = false;
80+
81+
} elseif($isParameter) {
82+
$parameter .= $character;
83+
} elseif($character === '/') {
84+
$regex .= '\\' . $character;
85+
} else {
86+
$regex .= $character;
87+
}
7788

78-
// Check if parameter of path matches, otherwise quit..
79-
if (is_null($parameter) && strtolower($path) != strtolower($url[$i])) {
80-
$matches = false;
81-
break;
82-
}
89+
$lastCharacter = $character;
90+
}
8391

84-
// Save parameter if we have one
85-
if ($parameter) {
86-
$parameterValue = $url[$i];
87-
$regex = (isset($this->parametersRegex[$parameter]) ? $this->parametersRegex[$parameter] : null);
92+
$parameterValues = array();
8893

89-
if ($regex !== null) {
90-
// Use the regular expression rule provided to filter the value
91-
$matches = array();
92-
preg_match('/' . $regex . '/is', $url[$i], $matches);
94+
if(preg_match('/^'.$regex.'$/is', $url, $parameterValues)) {
9395

94-
if (count($matches)) {
95-
$parameterValue = $matches[0];
96-
}
97-
}
96+
$parameters = array();
9897

99-
// Add parameter value, if it doesn't exist - replace it with null value
100-
$parameters[$parameter] = ($parameterValue === '') ? null : $parameterValue;
101-
}
98+
if(count($parameterNames)) {
99+
foreach($parameterNames as $name) {
100+
$parameters[$name] = isset($parameterValues[$name]) ? $parameterValues[$name] : null;
102101
}
103102
}
104103

105-
// This route matches
106-
if($matches) {
107-
$this->parameters = $parameters;
108-
return $this;
109-
}
104+
$this->parameters = $parameters;
105+
return $this;
110106
}
111107

112-
// No match here, move on...
113108
return null;
114109
}
115110

@@ -126,7 +121,11 @@ public function getUrl() {
126121
*/
127122
public function setUrl($url) {
128123

129-
$parameters = $this->parseParameters($url, true);
124+
$parameters = array();
125+
126+
preg_match_all('/'.self::PARAMETERS_REGEX_MATCH.'/is', $url, $parameters);
127+
128+
$parameters = $parameters[1];
130129

131130
if($parameters !== null) {
132131
foreach($parameters as $param) {

src/Pecee/SimpleRouter/SimpleRouter.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* ---------------------------
55
* Router helper class
66
* ---------------------------
7-
* This class is added so calls can be made staticly like Router::get() making the code look more pretty.
7+
* This class is added so calls can be made statically like Router::get() making the code look more pretty.
88
*/
99

1010
namespace Pecee\SimpleRouter;

0 commit comments

Comments
 (0)