PHP routing system
I'm trying to create a routing system based on annotations (something like on Recess Framework).
<?php
class MyController extends ActionController {
/** !Route GET /hello/$firstname/$lastname **/
public function helloAction($firstname, $lastname) {
echo('Hello '.$firstname.' '.$lastname);
}
}
?>
If I go to http://domain.com/hello/James/Bond I get
Hello James Bond
So I have two questions:
1) Is it a good idea? Pros and cons vs centralized routing system (like Zend Framework)开发者_JAVA百科. Maybe I don't see problems that my arise later with this routing technique.
2) How to check for duplicate routes if there is regexp in routes
<?php
class MyController extends ActionController {
/**
*!Route GET /test/$id = {
* id: [a-z0-9]
*}
**/
public function testAction($id) {
echo($id);
}
/**
*!Route GET /test/$id = {
* id: [0-9a-z]
*}
**/
public function otherTestAction($id) {
echo($id);
}
}
?>
I get two routes: /test/[a-z0-9]/
and /test/[0-9a-z]/
and if i go to http://domain.com/test/a12/
both routes are valid.
Thanks :)
Try using the Java annotation format which should be much easier to parse uniformly.
It looks something like this:
<?php
class MyController extends ActionController {
/**
@Route(get=/hello/$firstname/$lastname)
@OtherVal(var1=2,var2=foo)
@OtherVal2
**/
public function helloAction($firstname, $lastname) {
echo('Hello '.$firstname.' '.$lastname);
}
}
?>
And parse your annotation out with the following regex:
@(?P<annotation>[A-Za-z0-9_]*)(\((?P<params>[^\)]*))?
And of course cache these where possible to avoid repeated parsing.
Cons:
- It may be difficult to keep an overview of URL mappings of all methods in your server.
- To change a URL you have to change the source code, mapping is not separated from the application.
If the method signature and mapping are always as related as the example you might use reflection to extract the mapping where helloAction is picked up as /hello and each method argument is a subdirectory of this in the order as they're defined.
Then the annotation wouldn't need to duplicate the URL, only the fact that the method is an endpoint, something like this:
<?php
class MyController extends ActionController {
/** !endpoint(method=GET) **/
public function helloAction($firstname, $lastname) {
echo('Hello '.$firstname.' '.$lastname);
}
}
I think it's a good idea / Decoupling code and entry point seems pretty much used everywhere
Usually you don't check for it: the first one that matches wins.
Doing so is a great idea, as long as you cache the compiled routes in production. There is a cost associated to parsing your files when routing so you want to avoid that when not developing.
As for checking for duplicates, don't check by comparing the declaration. Simply check when routing. If two rules matches, throw a DuplicateRouteException
. So, when routing http://domain.com/test/a12/
, you'll see that both routes are valid and throw the exception.
精彩评论