mirror of
https://github.com/skipperbent/simple-php-router.git
synced 2026-06-17 00:37:52 +00:00
Ending trail/slash feature
- Feature: added support for slash in parameters (see readme). - Route: Fixed hardcoded param modifier. - Route: optimisations. - Updated Readme.
This commit is contained in:
+18
-2
@@ -42,6 +42,12 @@ class Url implements JsonSerializable
|
||||
*/
|
||||
private $path;
|
||||
|
||||
/**
|
||||
* Original path with no sanitization to ending slash
|
||||
* @var string|null
|
||||
*/
|
||||
private $originalPath;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
@@ -73,6 +79,7 @@ class Url implements JsonSerializable
|
||||
|
||||
if (isset($data['path']) === true) {
|
||||
$this->setPath($data['path']);
|
||||
$this->originalPath = $data['path'];
|
||||
}
|
||||
|
||||
$this->fragment = $data['fragment'] ?? null;
|
||||
@@ -226,6 +233,15 @@ class Url implements JsonSerializable
|
||||
return $this->path ?? '/';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get original path with no sanitization of ending trail/slash.
|
||||
* @return string|null
|
||||
*/
|
||||
public function getOriginalPath(): ?string
|
||||
{
|
||||
return $this->originalPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the url path
|
||||
*
|
||||
@@ -284,7 +300,7 @@ class Url implements JsonSerializable
|
||||
$params = [];
|
||||
parse_str($queryString, $params);
|
||||
|
||||
if(count($params) > 0) {
|
||||
if (count($params) > 0) {
|
||||
return $this->setParams($params);
|
||||
}
|
||||
|
||||
@@ -469,7 +485,7 @@ class Url implements JsonSerializable
|
||||
{
|
||||
$path = $this->path ?? '/';
|
||||
|
||||
if($includeParams === false) {
|
||||
if ($includeParams === false) {
|
||||
return $path;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,12 @@ abstract class Route implements IRoute
|
||||
*/
|
||||
protected $filterEmptyParams = true;
|
||||
|
||||
/**
|
||||
* If true the last parameter of the route will include ending trail/slash.
|
||||
* @var bool
|
||||
*/
|
||||
protected $slashParameterEnabled = false;
|
||||
|
||||
/**
|
||||
* Default regular expression used for parsing parameters.
|
||||
* @var string|null
|
||||
@@ -111,7 +117,7 @@ abstract class Route implements IRoute
|
||||
return $router->getClassLoader()->loadClassMethod($class, $method, $parameters);
|
||||
}
|
||||
|
||||
protected function parseParameters($route, $url, $parameterRegex = null): ?array
|
||||
protected function parseParameters($route, $url, Request $request, $parameterRegex = null): ?array
|
||||
{
|
||||
$regex = (strpos($route, $this->paramModifiers[0]) === false) ? null :
|
||||
sprintf
|
||||
@@ -123,8 +129,10 @@ abstract class Route implements IRoute
|
||||
);
|
||||
|
||||
// Ensures that host names/domains will work with parameters
|
||||
|
||||
if($route[0] == '{') $url = '/' . ltrim($url, '/');
|
||||
if ($route[0] === $this->paramModifiers[0]) {
|
||||
$url = '/' . ltrim($url, '/');
|
||||
}
|
||||
|
||||
$urlRegex = '';
|
||||
$parameters = [];
|
||||
|
||||
@@ -132,7 +140,7 @@ abstract class Route implements IRoute
|
||||
$urlRegex = preg_quote($route, '/');
|
||||
} else {
|
||||
|
||||
foreach (preg_split('/((\.?-?\/?){[^}]+})/', $route) as $key => $t) {
|
||||
foreach (preg_split('/((\.?-?\/?){[^' . $this->paramModifiers[1] . ']+' . $this->paramModifiers[1] . ')/', $route) as $key => $t) {
|
||||
|
||||
$regex = '';
|
||||
|
||||
@@ -154,6 +162,17 @@ abstract class Route implements IRoute
|
||||
}
|
||||
}
|
||||
|
||||
// Get name of last param
|
||||
/*$lastParam = null;
|
||||
$start = strrpos($route, '{');
|
||||
if($start > -1) {
|
||||
$param = substr($route, $start, strrpos($route, '}') + 1 - $start);
|
||||
if(str_ends_with($route, $param . '/')) {
|
||||
$lastParam = $param;
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
if (trim($urlRegex) === '' || (bool)preg_match(sprintf($this->urlRegex, $urlRegex), $url, $matches) === false) {
|
||||
return null;
|
||||
}
|
||||
@@ -167,7 +186,8 @@ abstract class Route implements IRoute
|
||||
$lastParams = [];
|
||||
|
||||
/* Only take matched parameters with name */
|
||||
foreach ((array)$parameters[1] as $name) {
|
||||
$originalPath = $request->getUrl()->getOriginalPath();
|
||||
foreach ((array)$parameters[1] as $i => $name) {
|
||||
|
||||
// Ignore parent parameters
|
||||
if (isset($groupParameters[$name]) === true) {
|
||||
@@ -175,10 +195,15 @@ abstract class Route implements IRoute
|
||||
continue;
|
||||
}
|
||||
|
||||
// If last parameter, use slash according to original path (non sanitized version)
|
||||
if ($this->slashParameterEnabled && ($i === count($parameters[1]) - 1) && str_ends_with($route, $this->paramModifiers[0] . $name . $this->paramModifiers[1] . '/') && $originalPath[strlen($originalPath) - 1] === '/') {
|
||||
$matches[$name] .= '/';
|
||||
}
|
||||
|
||||
$values[$name] = (isset($matches[$name]) === true && $matches[$name] !== '') ? $matches[$name] : null;
|
||||
}
|
||||
|
||||
$values = array_merge($values, $lastParams);
|
||||
$values += $lastParams;
|
||||
}
|
||||
|
||||
$this->originalParameters = $values;
|
||||
@@ -387,6 +412,17 @@ abstract class Route implements IRoute
|
||||
return $this->namespace ?? $this->defaultNamespace;
|
||||
}
|
||||
|
||||
public function setSlashParameterEnabled(bool $enabled): self
|
||||
{
|
||||
$this->slashParameterEnabled = $enabled;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getSlashParameterEnabled(): bool
|
||||
{
|
||||
return $this->slashParameterEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Export route settings to array so they can be merged with another route.
|
||||
*
|
||||
@@ -416,6 +452,10 @@ abstract class Route implements IRoute
|
||||
$values['defaultParameterRegex'] = $this->defaultParameterRegex;
|
||||
}
|
||||
|
||||
if ($this->slashParameterEnabled === true) {
|
||||
$values['includeSlash'] = $this->slashParameterEnabled;
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
@@ -453,6 +493,10 @@ abstract class Route implements IRoute
|
||||
$this->setDefaultParameterRegex($settings['defaultParameterRegex']);
|
||||
}
|
||||
|
||||
if (isset($settings['includeSlash']) === true) {
|
||||
$this->setSlashParameterEnabled($settings['includeSlash']);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ class RouteGroup extends Route implements IGroupRoute
|
||||
return true;
|
||||
}
|
||||
|
||||
$parameters = $this->parseParameters($domain, $request->getHost(), '.*');
|
||||
$parameters = $this->parseParameters($domain, $request->getHost(), $request, '.*');
|
||||
|
||||
if ($parameters !== null && count($parameters) !== 0) {
|
||||
$this->parameters = $parameters;
|
||||
@@ -60,7 +60,7 @@ class RouteGroup extends Route implements IGroupRoute
|
||||
|
||||
if ($this->prefix !== null) {
|
||||
/* Parse parameters from current route */
|
||||
$parameters = $this->parseParameters($this->prefix, $url);
|
||||
$parameters = $this->parseParameters($this->prefix, $url, $request);
|
||||
|
||||
/* If no custom regular expression or parameters was found on this route, we stop */
|
||||
if ($parameters === null) {
|
||||
|
||||
@@ -99,7 +99,7 @@ class RouteResource extends LoadableRoute implements IControllerRoute
|
||||
$route = rtrim($this->url, '/') . '/{id?}/{action?}';
|
||||
|
||||
/* Parse parameters from current route */
|
||||
$this->parameters = $this->parseParameters($route, $url);
|
||||
$this->parameters = $this->parseParameters($route, $url, $request);
|
||||
|
||||
/* If no custom regular expression or parameters was found on this route, we stop */
|
||||
if ($regexMatch === null && $this->parameters === null) {
|
||||
|
||||
@@ -31,7 +31,7 @@ class RouteUrl extends LoadableRoute
|
||||
}
|
||||
|
||||
/* Parse parameters from current route */
|
||||
$parameters = $this->parseParameters($this->url, $url);
|
||||
$parameters = $this->parseParameters($this->url, $url, $request);
|
||||
|
||||
/* If no custom regular expression or parameters was found on this route, we stop */
|
||||
if ($regexMatch === null && $parameters === null) {
|
||||
|
||||
Reference in New Issue
Block a user