Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Toro is a PHP router for developing RESTful web applications and APIs.
branch: master

This branch is 60 commits behind anandkunal:master

Fetching latest commit…

Cannot retrieve the latest commit at this time

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.

Something went wrong with that request. Please try again.