Toro is a PHP router for developing RESTful web applications and APIs. It is designed for minimalists who want to get work done.
- RESTful routing using strings, regular expressions, and defined types (
number,string,alpha) - Flexible error handling and callbacks via
ToroHook - Intuitive and self-documented core (
toro.php) - Tested with PHP 5.3 and above
The canonical "Hello, world" example:
<?php
class HelloHandler {
function get() {
echo "Hello, world";
}
}
Toro::serve(array(
"/" => "HelloHandler",
));Routing with Toro is simple:
<?php
Toro::serve(array(
"/" => "SplashHandler",
"/catalog/page/:number" => "CatalogHandler",
"/product/:alpha" => "ProductHandler",
"/manufacturer/:string" => "ManufacturerHandler"
));An application's route table is expressed as an associative array (route_pattern => handler). This is closely modeled after Tornado (Python). Routes are not expressed as anonymous functions to prevent unnecessary code duplication for RESTful dispatching.
From the above example, route stubs, such as :number, :string, and :alpha can be conveniently used instead of common regular expressions. Of course, regular expressions are still welcome. The previous example could also be expressed as:
<?php
Toro::serve(array(
"/" => "SplashHandler",
"/catalog/page/([0-9]+)" => "CatalogHandler",
"/product/([a-zA-Z0-9-_]+)" => "ProductHandler",
"/manufacturer/([a-zA-Z]+)" => "ManufacturerHandler"
));Pattern matches are passed in order as arguments to the handler's request method. In the case of ProductHandler above:
<?php
class ProductHandler {
function get($name) {
echo "You want to see product: $name";
}
}<?php
class ExampleHandler {
function get() {}
function post() {}
function get_xhr() {}
function post_xhr() {}
}From the above, you can see two emergent patterns.
-
Methods named after the HTTP request method (
GET,POST,PUT,DELETE) are automatically called. -
Appending
_xhrto a handler method automatically matches JSON/XMLHTTPRequestrequests. If the_xhrmethod is not implemented, then the given HTTP request method is called as a fallback.
As of v2.0.0, there are a total of five Toro-specific hooks (callbacks):
<?php
// Fired for 404 errors; must be defined before Toro::serve() call
ToroHook::add("404", function() {});
// Before/After callbacks in order
ToroHook::add("before_request", function() {});
ToroHook::add("before_handler", function() {});
ToroHook::add("after_handler", function() {});
ToroHook::add("after_request", function() {});before_handler and after_handler are defined within handler's constructor:
<?php
class SomeHandler {
function __construct() {
ToroHook::add("before_handler", function() { echo "Before"; });
ToroHook::add("after_handler", function() { echo "After"; });
}
function get() {
echo "I am some handler.";
}
}Hooks can also be stacked. Adding a hook pushes the provided anonymous function into an array. When a hook is fired, all of the functions are called sequentially.
Grab a copy of the repository and move toro.php to your htdocs or library directory. You may need to add the following snippet in your Apache virtual host configuration or .htaccess:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond $1 !^(index\.php)
RewriteRule ^(.*)$ /index.php/$1 [L]
- Toro was inspired by the Tornado Web Server (FriendFeed/Facebook)
- Berker Peksag, Martin Bean, Robbie Coleman, and John Kurkowski for bug fixes and patches
- Danillo César de O. Melo for
ToroHook - Jason Mooberry for code optimizations and feedback
Contributions to Toro are welcome via pull requests.
ToroPHP was created by Kunal Anand and released under the MIT License.