-
Notifications
You must be signed in to change notification settings - Fork 326
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Update Route matches #583
Update Route matches #583
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -397,9 +397,8 @@ public function filter($callback) | |
} | ||
|
||
/** | ||
* Tests if the route matches a given Request. A successful match will return | ||
* all of the routed parameters as an array. A failed match will return | ||
* boolean FALSE. | ||
* Tests if the route matches a given [Request]. A successful match will return | ||
* all of the routed parameters as an array, a failed match will return FALSE. | ||
* | ||
* // Params: controller = users, action = edit, id = 10 | ||
* $params = $route->matches(Request::factory('users/edit/10')); | ||
|
@@ -411,34 +410,29 @@ public function filter($callback) | |
* // Parse the parameters | ||
* } | ||
* | ||
* @param Request $request Request object to match | ||
* @return array on success | ||
* @return FALSE on failure | ||
* @param Request $request Request object to match | ||
* @return mixed | ||
*/ | ||
public function matches(Request $request) | ||
{ | ||
// Get the URI from the Request | ||
$uri = trim($request->uri(), '/'); | ||
|
||
if ( ! preg_match($this->_route_regex, $uri, $matches)) | ||
if ( ! preg_match($this->_route_regex, $uri, $params)) | ||
return FALSE; | ||
|
||
$params = array(); | ||
foreach ($matches as $key => $value) | ||
foreach ($params as $key => $value) | ||
{ | ||
// Delete all unnamed keys | ||
if (is_int($key)) | ||
{ | ||
// Skip all unnamed keys | ||
continue; | ||
unset($params[$key]); | ||
} | ||
|
||
// Set the value for all matched keys | ||
$params[$key] = $value; | ||
} | ||
|
||
foreach ($this->_defaults as $key => $value) | ||
{ | ||
if ( ! isset($params[$key]) OR $params[$key] === '') | ||
if ( ! isset($params[$key]) OR empty($params[$key])) | ||
{ | ||
// Set default values for any key that was not matched | ||
$params[$key] = $value; | ||
|
@@ -447,14 +441,27 @@ public function matches(Request $request) | |
|
||
if ( ! empty($params['controller'])) | ||
{ | ||
// PSR-0: Replace underscores with spaces, run ucwords, then replace underscore | ||
$params['controller'] = str_replace(' ', '_', ucwords(str_replace('_', ' ', $params['controller']))); | ||
if (strpos($params['controller'], '_') !== false) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Allcaps |
||
{ | ||
// PSR-0: Replace underscores with spaces, run ucwords, then replace underscore | ||
$params['controller'] = str_replace(' ', '_', ucwords(str_replace('_', ' ', $params['controller']))); | ||
} | ||
else | ||
{ | ||
$params['controller'] = ucfirst($params['controller']); | ||
} | ||
} | ||
|
||
if ( ! empty($params['directory'])) | ||
{ | ||
// PSR-0: Replace underscores with spaces, run ucwords, then replace underscore | ||
$params['directory'] = str_replace(' ', '_', ucwords(str_replace('_', ' ', $params['directory']))); | ||
$params['directory'] = ucwords(str_replace(array('\\', '/'), ' ', $params['directory'])); | ||
$params['directory'] = str_replace(' ', DIRECTORY_SEPARATOR, $params['directory']); | ||
|
||
if (strpos($params['directory'], '_') !== false) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Doesn't this also require an else block with I think this doesn't actually change behaviour, just saves some operations if there's no $param = preg_replace_callback(
'/(^|_)\w/',
function($matches){return strtoupper($matches[0]);},
$param
); Perhaps worth benchmarking? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. code for #571
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @acoulton also, your code create closure object at each call There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @WinterSilence #571 won't be merged, #578 is the implementation for that which is going to be much simpler. My snippet with closure was just for example, yes obviously you'd probably optimise/tidy up for implementation. |
||
{ | ||
// PSR-0: Replace underscores with spaces, run ucwords, then replace underscore | ||
$params['directory'] = str_replace(' ', '_', ucwords(str_replace('_', ' ', $params['directory']))); | ||
} | ||
} | ||
|
||
if ($this->_filters) | ||
|
@@ -473,10 +480,12 @@ public function matches(Request $request) | |
{ | ||
// Filter has modified the parameters | ||
$params = $return; | ||
// @todo if $return != $params, then uppercase values (directory, controller) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think if filters return controller/directory etc they should be responsible for returning in proper case. The only reason we do the case transformation is so that URLs can be lowercase. Application code should be case-sensitive just like everywhere else. In fact one use for a filter would be to transform a URL to some different casing convention eg Also if you are introducing There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
How do it? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For example name the PR "[WIP] Update Route matches", and if it's There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok, thanks add it in new PRs. |
||
} | ||
} | ||
} | ||
|
||
// @todo throw exception then some params not exists (controller, action) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Isn't that covered already in the request client? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I did not find it in request There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My mistake, assumed it was but you're right so yes we should throw here if required params are missing. |
||
return $params; | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be clearer and faster to use
array_filter
here?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To do this need create closure or there is basic function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well
is_string
is probably the opposite ofis_int
for this case?But a closure with
! is_numeric
might be safer to be sure it filters"1"
etc:There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
your code call function -> function create object -> function call object in cycle,
how it can work faster?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
array_filter
is often a lot faster than anything with foreach, because the loop and the data management all happens in native code - there are many fewer userland operations and stack changes. You're right I'd not allowed for the overhead of the closure though which is higher than I'd expected.We can't use my example above because
ARRAY_FILTER_USE_KEY
is PHP >= 5.6. For lower versions the best I've found is:I just did a quick benchmark of:
So it's basically always worth doing
array_filter
if there's a native function that does what you need, or if you can use a native function to find the values to reject and thenarray_diff_key
to strip them out of the array.Note also that it's fastest in the common (pure associative array) case, with only a small hit if it finds integer keys to remove.