Skip to content

Basic Routing

TIP

Leaf router is now separated from Leaf and is now available as an installable module via composer or the leaf cli.

Using Leaf router outside leaf

To use Leaf router outside of a leaf app, simply install the leaf router module:

composer require leafs/router

or

leaf install router

After this, you can use all of leaf router's functionality with the router class below.

Router class

The router class is the interface you interact with to perform any routing actions in your app. Leaf core directly integrates with the router class, which means that there is no need to use this class directly, if however, you are using leaf router outside of leaf, you will need to use the router class itself.

use Leaf\Router;

Router::get('/', 'PagesController@index');

Router::run();

Leaf router uses a single root file, to which all the server requests are redirected, it then takes these requests and matches them to rules you have defined. The results are then displayed to the user. Then entire routing process is actually based on this simple concept.

To make things simpler, we tied leaf router directly to the leaf instance, so once you initialize leaf, you can use routing.

<?php

require __DIR__ . '/vendor/autoload.php';

app()->get('/', function () {
  response()->json(['name' => 'Leaf']);
});

app()->run();
<?php

require __DIR__ . "/vendor/autoload.php";

$app = new \Leaf\App();

$app->get('/', function () use($app) {
  $app->response()->json(['name' => 'Leaf']);
});

$app->run();

Using a different router in Leaf

Although Leaf integrates leaf router directly, you are free to import and use any router you want.

  1. Install whatever you want
composer require imaginary/router
  1. Import and use it in your project
// initialise imaginary router
$imr = new Imaginary\Router();

$imr->get('/', function () {
  // you can still use leaf modules
  response()->json(['title' => 'hello']);
});
// initialise imaginary router
$imr = new Imaginary\Router();
$response = new Leaf\Http\Response();

$imr->get('/', function () use($response) {
  // you can still use leaf modules
  $response->json(['title' => 'hello']);
});

Creating Routes

IMPORTANT

From this point onwards, we will assume that you are using Leaf router inside a leaf app, as such, we will use the app syntax:

app()->get('/', function () {...});
$app->get('/', function () {...});

If however, you are using leaf router outside leaf, simply change app()/$app to the router class:

Router::get('/', function () {...});

You can define application routes using proxy methods on the Leaf\App instance. Leaf supports different types of requests, let's look at them.

GET

You can add a route that handles only GET HTTP requests with the Leaf router's get() method. It accepts two arguments:

  • The route pattern (with optional named placeholders or PCRE based patterns)
  • The route callback
app()->get('/home', function () {
  // your code
});
$app->get('/home', function () {
  // your code
});

POST

You can add a route that handles only POST HTTP requests with the Leaf router's post() method. It accepts two arguments:

  • The route pattern (with optional named placeholders or PCRE based patterns)
  • The route callback
app()->post('/users/add', function () {
  $user = request()->get('user');
  // create a new user
});
$app->post('/users/add', function () use($request) {
  $user = $request->get('user');
  // create a new user
});

Using Post Params View Request for more info on handling params

PUT requests

You can add a route that handles only PUT HTTP requests with the Leaf router’s put() method. It accepts two arguments:

  • The route pattern (with optional named placeholders or PCRE based patterns)
  • The route callback
app()->put('/book/edit/{id}', function ($id) {
  // your code
});
$app->put('/book/edit/{id}', function ($id) {
  // your code
});

DELETE requests

You can add a route that handles only DELETE HTTP requests with the Leaf router's delete() method. It accepts two arguments:

  • The route pattern (with optional named placeholders or PCRE based patterns)
  • The route callback
app()->delete('/quotes/{id}', function ($id) {
  // delete quote
});
$app->delete('/quotes/{id}', function ($id) {
  // delete quote
});

OPTIONS requests

You can add a route that handles only OPTIONS HTTP requests with the Leaf router's options() method. It accepts two arguments:

  • The route pattern (with optional named placeholders or PCRE based patterns)
  • The route callback
app()->options('/quotes/{id}', function ($id) {
  // return headers
});
$app->options('/quotes/{id}', function ($id) {
  // return headers
});

PATCH requests

You can add a route that handles only PATCH HTTP requests with the Leaf router's patch() method. It accepts two arguments:

  • The route pattern (with optional named placeholders or PCRE based patterns)
  • The route callback
app()->patch('/post/{id}', function ($id) {
  // your code
});
$app->patch('/post/{id}', function ($id) {
  // your code
});

ALL requests

You can add a route that handles all HTTP requests with the Leaf router's all() method. It accepts two arguments:

  • The route pattern (with optional named placeholders or PCRE based patterns)
  • The route callback
app()->all('/post/{id}', function ($id) {
  // your code
});
$app->all('/post/{id}', function ($id) {
  // your code
});

Resource Routes

This section assumes you've read working with controllers. In an MVC application, controllers play a major role as they're the bridge between your view and your model.

A resource route simply creates all the routes needed to successfully handle a particular feature. This sounds a bit bleak, let's look at an example.

app()->resource('/posts', 'PostsController');

app()->run();
$app->resource('/posts', 'PostsController');

$app->run();

The code above is equivalent to this:

app()->match('GET|HEAD', '/posts', "$controller@index");
app()->post('/posts', "$controller@store");
app()->match('GET|HEAD', '/posts/create', "$controller@create");
app()->match('POST|DELETE', '/posts/{id}/delete', "$controller@destroy");
app()->match('POST|PUT|PATCH', '/posts/{id}/edit', "$controller@update");
app()->match('GET|HEAD', '/posts/{id}/edit', "$controller@edit");
app()->match('GET|HEAD', '/posts/{id}', "$controller@show");

app()->run();
$app->match('GET|HEAD', '/posts', "$controller@index");
$app->post('/posts', "$controller@store");
$app->match('GET|HEAD', '/posts/create', "$controller@create");
$app->match('POST|DELETE', '/posts/{id}/delete', "$controller@destroy");
$app->match('POST|PUT|PATCH', '/posts/{id}/edit', "$controller@update");
$app->match('GET|HEAD', '/posts/{id}/edit', "$controller@edit");
$app->match('GET|HEAD', '/posts/{id}', "$controller@show");

$app->run();

Resource routes are handled by a resource controller.

Route "Hooking"

You can add a route that handles a couple of HTTP methods with the Leaf router's match() method. It accepts three arguments:

  • The HTTP method(s) seperated by |
  • The route pattern (with optional named placeholders or PCRE based patterns)
  • The route callback
app()->match('GET|POST', '/people', function () {
  // your code
});
$app->match('GET|POST', '/people', function () {
  // your code
});

Running your routes

After setting all the routes, you'll need to dispatch the routes. This is achieved through Leaf's run() method.

app()->run();
$app->run();

Route options

Route options simply allow you to configure the way groups and individual routes by passing in additional parameters. In actual sense, all new features were generated as a result of this single feature. Let's see how it works.

Leaf route handlers are usually callable functions like this:

app()->get("/home", function () {
  echo 'User Home';
});
$app->get("/home", function () {
  echo 'User Home';
});

Or sometimes controllers, like this:

app()->get('/home', 'HomeController@index');
$app->get('/home', 'HomeController@index');

This means there was no space to chain additional items to the route, this is solved by route options.

app()->get('/home', ['name' => 'home', function () {
  echo 'User Home';
}]);
$app->get('/home', ['name' => 'home', function () {
  echo 'User Home';
}]);

When an array is passed into a leaf route as the handler, leaf will take all key => value as options for that route, the first non key-value function or controller in the array is taken as the handler.

app()->get('/form', ['name' => 'userForm', 'FormsController@index']);
$app->get('/form', ['name' => 'userForm', 'FormsController@index']);

As mentioned before, this feature is also available on groups:

app()->group('/user', ['namespace' => '\\', function () {
    // ...
}]);
$app->group('/user', ['namespace' => '\\', function () {
    // ...
}]);

This doesn't mean that you should always pass in an array, if you don't need the other options, you can pass in your function or controller directly as you've always done.

Naming your routes

You can give names to your routes which allows you to use your route names for navigation instead of your route paths. This feature is heavily inspired by vue-router.

app()->get('/home', ['name' => 'home', function () {
  echo 'User Home';
}]);
$app->get('/home', ['name' => 'home', function () {
  echo 'User Home';
}]);

Getting a route by its name

You can also get the route path by its name.

app()->route('home'); // Would return: /home
$app->route('home'); // Would return: /home

Also, if you have routes with named parameters, you can do as follows:

Route 1:

app()->get('/movies/{movieId}', ['name' => 'movies', function () {
  echo 'User Movies';
}]);

app()->route('movies', 'my-movie') // Would return: /movies/my-movie
$app->get('/movies/{movieId}', ['name' => 'movies', function () {
  echo 'User Movies';
}]);

$app->route('movies', 'my-movie') // Would return: /movies/my-movie

Route 2:

app()->get('/movies/{movieId}/photos/{photoId}', ['name' => 'moviesAndPhotos', function () {
  echo 'User Movies and Photos';
}]);

app()->route('moviesAndPhotos', ['movieId' => 'my-movie', 'photoId' => 'my-photo']);

// Would return: /movies/my-movie/photos/my-photo
$app->get('/movies/{movieId}/photos/{photoId}', ['name' => 'moviesAndPhotos', function () {
  echo 'User Movies and Photos';
}]);

$app->route('moviesAndPhotos', ['movieId' => 'my-movie', 'photoId' => 'my-photo']);

// Would return: /movies/my-movie/photos/my-photo

Pushing to a route

This is simply redirecting to a route and can be done using push. push also allows you to reference the route by it's name instead of it's path.

app()->push('/home');
$app->push('/home');

When an array is passed into push, Leaf will search for a route name matching the string in the array and redirect to that route:

// home was defined above
app()->push(['home']);
// home was defined above
$app->push(['home']);

Getting the current route

There are times when you need to get information about the current route from within one of your route handlers, views or controllers. For example, you may wish to generate a URL for the current route or redirect to the current route. You may also need to access the route's parameters. You may do all of this using the Router::getRoute() method:

app()->get('/home', ['name' => 'home', function () {
  $route = app()->getRoute();
  echo $route['name'];
}]);
$app->get('/home', ['name' => 'home', function () use ($app) {
  $route = $app->getRoute();
  echo $route['name'];
}]);

The output of getRoute() looks something like this:

{
  "pattern": "/users/(.*?)",
  "path": "/users/1",
  "method": "GET",
  "name": "mycontroller",
  "handler": "MyNamespace\\Controller@index",
  "params": [
    "1"
  ]
}
  • pattern is the route pattern
  • path is the current route path
  • method is the current route method
  • name is the current route name
  • handler is the current route handler (custom function or controller)
  • params is an array of the current route's parameters (dynamic values)
Basic Routing has loaded