Toro is a PHP router for developing RESTful web applications and APIs.
Pull request Compare This branch is 63 commits behind anandkunal:master.
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
examples
.gitignore
LICENSE
README.md
toro.php

README.md

Toro

Toro is a PHP router for developing RESTful web applications and APIs. It is designed for minimalists who want to get work done.

Quick Links

Features

  • 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

"Hello, world"

The canonical "Hello, world" example:

<?php

class HelloHandler {
    function get() {
        echo "Hello, world";
    }
}

Toro::serve(array(
    "/" => "HelloHandler",
));

Routing Basics

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";
    }
}

RESTful Handlers

<?php

class ExampleHandler {
    function get() {}
    function post() {}
    function get_xhr() {}
    function post_xhr() {}
}

From the above, you can see two emergent patterns.

  1. Methods named after the HTTP request method (GET, POST, PUT, DELETE) are automatically called.

  2. Appending _xhr to a handler method automatically matches JSON/XMLHTTPRequest requests. If the _xhr method is not implemented, then the given HTTP request method is called as a fallback.

ToroHook (Callbacks)

As of v2.0.0, there are a total of five Toro-specific hooks (callbacks):

<?php

// Fired for 404 errors
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.

Installation

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]

Contributions

Contributions to Toro are welcome via pull requests.

License

ToroPHP was created by Kunal Anand and released under the MIT License.