Introduction
In this article I’ll present the routing mechanism inside my home-made php framework : Plevin.
The routing mechanism inside Plevin is quite simple. Every controller (named here handler) is market with an annotation and a file is generated at website initialisation.
Controller (handler) class
Here you can see a simple example of controller. The CategoryHandler class is marked as handler and manage specified urls.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | /** * @HandleURL(pattern="/categories") */ class CategoryHandler{ /** * @Injection(id="Logger") * @var Plevin\logging\Logger */ private $logger; /** * @HandleURL(pattern="/$") */ public function showMain(){ echo "Show main page"; } /** * @HandleURL(pattern="/{category}") */ public function showCategory($categoryName = "main") { echo "Template content for category $categoryName"; } /** * Show the specified object, from the specified category * @HandleURL(pattern="/{category}/{object}$") */ public function showObject($categoryName, $objectName) { echo "Template content for category $categoryName, object $objectName"; } } |
The handler class has a function for every managed url. Each function can receive url parameters and have to generate a template.
In the example above a simple injection is made, the handler receive a reference to the framework’s logger.
Generated file
On first execution, the CategoryHandler is analysed and the corresponding generated cached file is visible here :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | if(preg_match("@^/categories@", $query)){ if(!file_exists("/path/to/app/Site/handler/CategoryHandler.php") || filemtime(__FILE__) < filemtime("/path/to/app/Site/handler/CategoryHandler.php")) throw new \Plevin\cache\CacheOutOfDateException("Class Shop2\handler\CategoryHandler out of date !"); if(preg_match("@^/categories/$@", $query, $params)){ $injection = new \Plevin\injection\InjectionProxy("\handler\CategoryHandler"); array_shift($params); $injection->__call("showMain", $params); return true; } if(preg_match("@^/categories/((?:[a-zA-Z0-9]|_|-)+)$@", $query, $params)){ $injection = new \Plevin\injection\InjectionProxy("\handler\CategoryHandler"); array_shift($params); $injection->__call("showCategory", $params); return true; } if(preg_match("@^/categories/((?:[a-zA-Z0-9]|_|-)+)/((?:[a-zA-Z0-9]|_|-)+)$@", $query, $params)){ $injection = new \Plevin\injection\InjectionProxy("\handler\CategoryHandler"); array_shift($params); $injection->__call("showObject", $params); return true; } } |
First of all, the generated file check if the handler has been modified since last file generation. When the generated file is older than the handler, an CacheOutOfDateException is thrown and the framework generate a new cache file.
The controller routing is managed with some simple preg_match function. Before any call to the handler’s method, a new instance of InjectionProxy is created and the correct handler’s method class is made through the newly generated InjectionProxy. Every dependency injection is managed by the InjectionProxy (in this case, the logger is injected if necessary). For more informations about dependency injection, an article will be available soon.
The generated file return true when an url is recognized and managed by a handler. When no handler manage a given url, false is returned and a simpl 404 error is generated.
Link creation
Plevin framework provide a great flexibility in link management. A link to a specific page is a link to a specific controller’s method with specific parameters. An URLManager is provided to help developer creating links. The code below show how to create a link to a specific controller’s method :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /** * @HandleURL(pattern="/inscription") */ class InscriptionHandler { /** * @Injection(id="URLManager") */ private $urlManager; /** * @HandleURL(pattern="/$") */ public function showInscriptionForm() { ... $link = $this->urlManager->getURL("App\handler\CategoryHandler->showCategory", array("category" => $currentCategory)); ... } } |
In the code above, the $link variable contains the path to the showCategory() method of the CategoryHandler controller. When urls contain parameters, they can be given through getURL() second argument.
The generated url is based on the @HandleURL annotation of the targeted method.
Conclusion
The url management provided by Plevin is flexible enough to change easly controllers’ paths. The main disadvantage of this operating way is the high dependency to the destination handler’s name (on refactoring you have to recreate every links).
A better method is the one used by Symfony 2 : an url file containing an id for every link. Every id target a controller’s method and links are made with a reference to a specific id.

