{"action":"created","issue":{"url":"https://api.github.com/repos/nikic/FastRoute/issues/171","repository_url":"https://api.github.com/repos/nikic/FastRoute","labels_url":"https://api.github.com/repos/nikic/FastRoute/issues/171/labels{/name}","comments_url":"https://api.github.com/repos/nikic/FastRoute/issues/171/comments","events_url":"https://api.github.com/repos/nikic/FastRoute/issues/171/events","html_url":"https://github.com/nikic/FastRoute/issues/171","id":358375855,"node_id":"MDU6SXNzdWUzNTgzNzU4NTU=","number":171,"title":"Return value too ambiguous","user":{"login":"XedinUnknown","id":1428973,"node_id":"MDQ6VXNlcjE0Mjg5NzM=","avatar_url":"https://avatars1.githubusercontent.com/u/1428973?v=4","gravatar_id":"","url":"https://api.github.com/users/XedinUnknown","html_url":"https://github.com/XedinUnknown","followers_url":"https://api.github.com/users/XedinUnknown/followers","following_url":"https://api.github.com/users/XedinUnknown/following{/other_user}","gists_url":"https://api.github.com/users/XedinUnknown/gists{/gist_id}","starred_url":"https://api.github.com/users/XedinUnknown/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/XedinUnknown/subscriptions","organizations_url":"https://api.github.com/users/XedinUnknown/orgs","repos_url":"https://api.github.com/users/XedinUnknown/repos","events_url":"https://api.github.com/users/XedinUnknown/events{/privacy}","received_events_url":"https://api.github.com/users/XedinUnknown/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":0,"created_at":"2018-09-09T12:46:29Z","updated_at":"2018-09-22T11:44:04Z","closed_at":null,"author_association":"NONE","body":"Hi!\r\n\r\nYour library is great. So great in fact that Zend Expressive has an adapter for it. So, thank you very much for this.\r\n\r\nWhat I find wrong with it is the resolution value, i.e. the return value of `dispatch()` (which is already ambiguous because the route is not dispatched, but rather resolved; but anyhow). And by that I mean the [weird array](https://github.com/nikic/FastRoute#dispatching-a-uri): both the type of the returned value, and the non-uniform structure. It complicates logic that consumes `dispatch()`, and makes type documentation or hinting impossible.\r\n\r\n## Proposal\r\nIMO, a method must do what it is made to do, or fail. And by fail, I mean throw. So, `dispatch()` could be changed to either resolve the URL+method combination, or throw an exception. The successful result could be a `callable` - the callable that is given to the [`Route`][] as the handler. In the case of error, two exception types may be added to mean the inability to resolve, e.g.\r\n\r\n- `CouldNotResolveException` - No route could be found for the URI+method combination.\r\n- `MethodNotAllowedException extends CouldNotResolveException` - The \"endpoint\" was found, but no method matched. This can have a `getAllowedMethods(): array<string>` method, which would return the array of allowed methods.\r\n\r\nThe above would allow a structured approach to route resolution, delegation of error handling, stricter type handling. In my case, I used [`ellipse/dispatcher`][]. I could then much more reliably expect a callable that returns a [`RequestHandlerInterface`][].\r\n\r\n## Further\r\nOptionally, since the above changes would lead to a BC break, you could go even further and change things around a bit. For example, have [routes][`Route`] be value objects that expose their URL, method, and handler, and outsource the matching to something else.\r\n\r\n[`ellipse/dispatcher`]: https://github.com/ellipsephp/dispatcher\r\n[`RequestHandlerInterface`]: https://github.com/php-fig/http-server-handler/blob/master/src/RequestHandlerInterface.php\r\n[`Route`]: https://github.com/nikic/FastRoute/blob/master/src/Route.php"},"comment":{"url":"https://api.github.com/repos/nikic/FastRoute/issues/comments/423738481","html_url":"https://github.com/nikic/FastRoute/issues/171#issuecomment-423738481","issue_url":"https://api.github.com/repos/nikic/FastRoute/issues/171","id":423738481,"node_id":"MDEyOklzc3VlQ29tbWVudDQyMzczODQ4MQ==","user":{"login":"bwoebi","id":3154871,"node_id":"MDQ6VXNlcjMxNTQ4NzE=","avatar_url":"https://avatars2.githubusercontent.com/u/3154871?v=4","gravatar_id":"","url":"https://api.github.com/users/bwoebi","html_url":"https://github.com/bwoebi","followers_url":"https://api.github.com/users/bwoebi/followers","following_url":"https://api.github.com/users/bwoebi/following{/other_user}","gists_url":"https://api.github.com/users/bwoebi/gists{/gist_id}","starred_url":"https://api.github.com/users/bwoebi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bwoebi/subscriptions","organizations_url":"https://api.github.com/users/bwoebi/orgs","repos_url":"https://api.github.com/users/bwoebi/repos","events_url":"https://api.github.com/users/bwoebi/events{/privacy}","received_events_url":"https://api.github.com/users/bwoebi/received_events","type":"User","site_admin":false},"created_at":"2018-09-22T11:44:04Z","updated_at":"2018-09-22T11:44:04Z","author_association":"CONTRIBUTOR","body":"While I agree on the idea of using value objects, I do not think that using exceptions is the correct way to handle the no-match case.\r\n\r\nThis is a low-level library providing base routing functionality, not a high-level wrapper who considers a non-match exceptional. A non-match is, from the perspective of this library a very valid outcome and thus shouldn't throw."}}
{"actor":{"display_login":"bwoebi"}}