Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/MonishAMPT/fastroute-code/llms.txt

Use this file to discover all available pages before exploring further.

As your FastRoute application grows, organizing routes into separate files becomes essential for maintainability and team collaboration.

Why Organize Routes?

Maintainability

Easier to find and update specific routes

Separation of Concerns

Keep different types of routes logically separated

Team Collaboration

Multiple developers can work on different route files

Scalability

Add new features without cluttering existing files

Route File Pattern

FastRoute uses a simple pattern for organizing routes into separate files:
  1. Create route files that return a closure
  2. The closure accepts a RouteCollector instance
  3. Load and call the closure in your main dispatcher

Loading Route Files

In your main index.php, load route files using require and call them:
index.php
$dispatcher = FastRoute\simpleDispatcher(function(RouteCollector $r) {
    // Load API routes
    $apiRoutes = require __DIR__ . '/routes/api.php';
    $apiRoutes($r);
    
    // Load web routes
    $webRoutes = require __DIR__ . '/routes/web.php';
    $webRoutes($r);
});
The require statement returns the value from the route file (a closure), which is then called with the RouteCollector instance.

Creating Route Files

API Routes File

Create routes/api.php that returns a closure:
routes/api.php
<?php

use FastRoute\RouteCollector;
use FastRoute\ConfigureRoutes;
include __DIR__."/../v1/test.php";
$obj = new testing;

return function (RouteCollector $r) {
    $obj = new testing;
    
    $r->addGroup('/api/projects', function (FastRoute\RouteCollector $r) use($obj) {
        $r->get('/testing/test', function() use($obj) {
            $obj->hello();
        });
        $r->get("/", function() use($obj) {
            $obj->display(1);
        });
    });
    
    $r->addRoute('GET', '/api/test', 'test_get');
    $r->addRoute('POST', '/api/test', 'test_post');
};

Web Routes File

Create routes/web.php for HTML-returning routes:
routes/web.php
<?php

use FastRoute\RouteCollector;

return function (RouteCollector $r) {

    $r->get('/', function() {
        require __DIR__ . '/../views/main.php';
    });

    $r->get('/about', function() {
        require __DIR__ . '/../views/about.php';
    });
};

Advanced Organization Patterns

Organizing by Feature

For larger applications, organize routes by feature:
routes/
├── api/
│   ├── users.php
│   ├── products.php
│   └── orders.php
├── web/
│   ├── public.php
│   └── admin.php
└── index.php
Create a loader file:
routes/api/index.php
<?php

use FastRoute\RouteCollector;

return function (RouteCollector $r) {
    // Load user routes
    $userRoutes = require __DIR__ . '/users.php';
    $userRoutes($r);
    
    // Load product routes
    $productRoutes = require __DIR__ . '/products.php';
    $productRoutes($r);
    
    // Load order routes
    $orderRoutes = require __DIR__ . '/orders.php';
    $orderRoutes($r);
};

Organizing by Version

For APIs with versioning:
routes/
├── api/
│   ├── v1/
│   │   ├── users.php
│   │   └── products.php
│   └── v2/
│       ├── users.php
│       └── products.php
└── web.php
routes/api/v1/users.php
<?php

use FastRoute\RouteCollector;

return function (RouteCollector $r) {
    $r->addGroup('/api/v1/users', function (RouteCollector $r) {
        $r->get('/', 'v1_list_users');
        $r->get('/{id:\d+}', 'v1_get_user');
        $r->post('/', 'v1_create_user');
    });
};

Sharing Dependencies

When route files need to share dependencies (like class instances), you have several options:

Option 1: Include at File Level

routes/api.php
include __DIR__."/../v1/test.php";
$obj = new testing;

return function (RouteCollector $r) {
    $obj = new testing;
    
    $r->get('/api/class', function() use($obj) {
        $obj->hello();
    });
};

Option 2: Dependency Injection Container

For larger applications, consider using a DI container:
// Create container
$container = new \Pimple\Container();
$container['testing'] = function() {
    return new testing();
};

// Pass to route files
$apiRoutes = require __DIR__ . '/routes/api.php';
$apiRoutes($r, $container);

Option 3: Global Registry

For simple cases, use a registry pattern:
class Registry {
    private static $instances = [];
    
    public static function set($key, $instance) {
        self::$instances[$key] = $instance;
    }
    
    public static function get($key) {
        return self::$instances[$key] ?? null;
    }
}

Route File Structure

Every route file should follow this structure:
<?php

// 1. Import necessary classes
use FastRoute\RouteCollector;

// 2. Load dependencies (if needed)
include __DIR__ . '/../handlers/UserHandler.php';

// 3. Create instances (if needed)
$handler = new UserHandler();

// 4. Return closure that registers routes
return function (RouteCollector $r) use ($handler) {
    // 5. Define routes
    $r->addGroup('/api/users', function (RouteCollector $r) use ($handler) {
        $r->get('/', function() use ($handler) {
            $handler->list();
        });
        $r->get('/{id:\d+}', function($vars) use ($handler) {
            $handler->get($vars['id']);
        });
    });
};
This consistent structure makes it easy for team members to understand and maintain route files.

Complete Example

Here’s how the complete routing system works together:

Main Entry Point

index.php
<?php

require 'vendor/autoload.php';

use FastRoute\RouteCollector;

$request_uri = $_SERVER['REQUEST_URI'];
$method = $_SERVER['REQUEST_METHOD'];

$cleaned_uri = str_replace('/apitest', '', $request_uri);
$uri = parse_url($cleaned_uri, PHP_URL_PATH);

$dispatcher = FastRoute\simpleDispatcher(function(RouteCollector $r) {
    // Load API routes
    $apiRoutes = require __DIR__ . '/routes/api.php';
    $apiRoutes($r);
    
    // Load web routes
    $webRoutes = require __DIR__ . '/routes/web.php';
    $webRoutes($r);
});

$routeInfo = $dispatcher->dispatch($method, $uri);

if (strpos($uri, '/api/') === 0) {
    header('Content-Type: application/json; charset=utf-8');
} else {
    header('Content-Type: text/html; charset=utf-8');
}

switch ($routeInfo[0]) {
    case FastRoute\Dispatcher::NOT_FOUND:
        header("HTTP/1.1 404 Not Found");
        echo json_encode(["message" => "Route not found"]);
        break;

    case FastRoute\Dispatcher::METHOD_NOT_ALLOWED:
        header("HTTP/1.1 405 Method Not Allowed");
        echo json_encode(["message" => "Method not allowed"]);
        break;

    case FastRoute\Dispatcher::FOUND:
        $handler = $routeInfo[1];
        $var = $routeInfo[2];
        call_user_func($handler, $var);
        break;
}

Best Practices

Each route file should handle a single resource or feature area. Don’t mix unrelated routes.
Name route files after the resources they handle (e.g., users.php, products.php).
Add comments to describe complex routes or special requirements:
// Requires authentication token in header
$r->get('/api/users/{id}', 'get_user');

Scaling Considerations

For Small Projects (< 50 routes)

  • Use 2-3 route files (api.php, web.php)
  • Keep handlers in main file or simple classes

For Medium Projects (50-200 routes)

  • Organize by feature (users, products, orders)
  • Use class-based handlers
  • Consider versioning for APIs

For Large Projects (200+ routes)

  • Organize by feature AND version
  • Use dependency injection
  • Implement middleware pattern
  • Consider route caching

Next Steps

Project Structure

Review the recommended project structure

Route Handlers

Learn about different handler types

API Routes

Create organized API endpoints

Web Routes

Organize your web routes effectively

Build docs developers (and LLMs) love