[Routing] Implement bug fixes and enhancements (from @Tobion) #3876
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This is mainly #3754 with some minor formatting changes.
Original PR message from @Tobion:
Here a list of what is fixed. Tests pass.
The
RouteCollection
statesBut this is not true for
->addCollection()
but only for->add()
. addCollection does not remove routes with the same name in its parents (only in its children). I don't think this is on purpose.So I fixed it by making sure there can only be one route per name in all connected collections. This way we can also simplify
->get()
and->remove()
and improve performance since we can stop iterating recursively when we found the first and only route with a given name.See
testUniqueRouteWithGivenName
that fails in the old code but works now.There was an bug with
$collection->addPrefix('0');
that didn't apply the starting slash. Fixed and test case added.There is an issue with
->get()
that I also think is not intended. Currently it allows to access a sub-RouteCollection by specifing $name as array integer index. But according to the PHPdoc you should only be allowed to receive a Route instance and not a RouteCollection.See
testGet
that has a failing test case. I fixed this behavior.Then I recognized that
->addCollection
depended on the order of applying them. Sohad a different pattern result from
Fixed and test case added. See
testPatternDoesNotChangeWhenDefinitionOrderChanges
.PHP could have ended in an infinite loop when one tried to add an existing RouteCollection to the tree. Fixed by throwing an exception when this situation is detected. See tests
testCannotSelfJoinCollection
andtestCannotAddExistingCollectionToTree
.I made
setParent()
private because its not useful outside the class itself. Andremove()
also removes the route from its parents. Added publicgetRoot()
method.The
Route
class throwed a PHP warning when trying to set an empty requirement.Fixed issue [Routing] optimization in PhpMatcherDumper produces wrong result #3777. See discussion there for more info. I fixed it by removing the over-optimization that was introduced in 91f4097 but didn't work properly. One cannot reorder the route definitions, as is was done, because then the wrong route might me matched before the correct one. If one really wanted to do that, it would require to calculate the intersection of two regular expressions to determine if they can be grouped together (a tool that would also be useful to check whether a route is unreachable, see discussion in [RFC][Routing] Improve the current matching process #3678) We can only safely optimize routes with a static prefix within a RouteCollection, not across multiple RouteCollectio 8000 ns with different parents. This is especially true when using variables and regular expressions requirements.
I could however apply an optimization that was missing yet: Collections with a single route were missing the static prefix optimization with
0 === strpos()
.Fixed an issue where the
PhpMatcherDumper
would not apply the optimization if the root collection to be dumped has a prefix itself. For this I had to rewritecompileRoutes
. It is also much easier to understand now. Addionally I added many comments and PHPdoc because complex recursive methods like this are still hard to grasp.I added a test case for this (
url_matcher3.php
).Fix that
Route::compile
needs to recompile a route once it is modified. Otherwise we have a wrong result. Test case added.