Route
is a dynamic routing package for PHP applications, designed to simplify the creation of RESTful routes.
composer require abdelrhman-saeed/route
-
Entry Point File: Create an entry point file for your application (e.g.,
index.php
). -
Server Configuration: Redirect all requests to this entry point file.
Example using PHP's built-in server:
php -S 127.0.0.1:8000
-
Routes File: Create a separate file to define your routes (e.g.,
routes.php
). You can store it anywhere in your project.
index.php:
<?php
use AbdelrhmanSaeed\Route\Api\Route;
use Symfony\Component\HttpFoundation\{Request, Response};
// Initialize the routing system
Route::setup('routes.php', Request::createFromGlobals(), new Response);
routes.php:
use AbdelrhmanSaeed\Route\Api\Route;
use App\Controllers\SomeKindOfController;
// Define routes with dynamic segments
Route::get('users/{user}/posts/{post}', function (int $user, int $post) {
var_dump($user, $post);
});
// Use a controller to handle requests
Route::get('posts/{post}/comments/{comment}', [SomeKindOfController::class, 'someMethod']);
// Define routes with optional segments
Route::get('search/users/{user}/{filter?}', function (int $user, ?string $filter = null) {
// Handle search logic
});
// Supported HTTP methods: ['get', 'post', 'put', 'patch', 'delete']
Route::post('test', function () {
// Handle POST request
});
Route::put('test', function () {
// Handle PUT request
});
// Define multiple methods for a single route
Route::match(['put', 'patch', 'delete'], 'test', function () {
// Handle multiple request types
});
// Define a route for all HTTP methods
Route::any('test', function () {
// Handle any HTTP method
});
You can apply constraints to route segments to validate their format.
use AbdelrhmanSaeed\Route\Endpoints\Rest\Constraints\ConstraintsInterface;
use AbdelrhmanSaeed\Route\Api\Route;
// Define a constraint using regex
Route::get('users/{user}', fn (int $user) => var_dump($user))
->where('user', '[A-z]+');
// Use predefined constraints from ConstraintsInterface
Route::get('users/{user}/posts/{post}', function (int $user, string $post) {
// Handle request
})
->where('user', ConstraintsInterface::NUM)
->where('post', ConstraintsInterface::ALPHANUM);
// Specify allowed values for a segment
Route::get('oauthcallback/{server}', function (string $server) {
// Handle OAuth callback
})
->whereIn('server', ['facebook', 'google']);
To add middleware to your routes, extend the AbdelrhmanSaeed\Route\Middleware
class and implement the handle()
method.
use AbdelrhmanSaeed\Route\Middleware;
use Symfony\Component\HttpFoundation\Request;
class RedirectIfAuthenticated extends Middleware
{
public function handle(Request $request): void
{
// Perform checks before proceeding
parent::handle($request);
}
}
Assign middleware to a route:
Route::get('login', function () {
// Login logic
})->setMiddlewares(RedirectIfAuthenticated::class);
The Route::resource()
method automatically generates RESTful routes for a given controller.
Route::resource('users', UserController::class);
This will generate:
GET /users
→UserController::index()
POST /users
→UserController::save()
GET /users/{user}
→UserController::show(mixed $user)
PUT, PATCH /users/{user}
→UserController::update(mixed $user)
DELETE /users/{user}
→UserController::delete(mixed $user)
If you set the api
parameter to false
, two additional routes will be generated:
GET /users/create
→UserController::create()
GET /users/{user}/edit
→UserController::edit(mixed $user)
Route::resource('users', UserController::class, false);
You can define nested resource routes using dot notation:
Route::resource('users.posts', PostController::class);
This will generate routes like:
GET /users/{user}/posts
→PostController::index()
POST /users/{user}/posts
→PostController::save()
GET /users/{user}/posts/{post}
→PostController::show(mixed $post)
Apply constraints to nested routes:
Route::resource('users.posts', PostController::class)
->where('users', ConstraintsInterface::NUM)
->where('posts', ConstraintsInterface::ALPHANUM);
Shallow nesting removes the parent ID from child routes when it's unnecessary.
Route::resource('users.posts', PostController::class, shallow: true);
This will generate routes like:
GET /users/posts
→PostController::index()
POST /users/posts
→PostController::save()
GET /users/posts/{post}
→PostController::show(mixed $post)
You can group routes and assign a middleware to all of them:
Route::setMiddlewares(RedirectIfAuthenticated::class)
->group(function () {
Route::get('test', function () {
// Handle request
});
Route::resource('posts', PostController::class);
});
Group routes by a common controller:
Route::controller(SomeController::class)
->group(function () {
Route::get('someroute', 'methodName');
Route::post('posts', 'store');
});
You can also combine controller and middleware grouping:
Route::controller(SomeController::class)
->setMiddlewares(SomeMiddleware::class)
->group(function () {
Route::get('route', 'method');
Route::post('posts', 'store');
});
Define a custom action for 404 responses:
Route::notFound(function () {
// Handle 404 error
echo 'Page not found';
});
If not defined, a simple 404 HTTP message will be returned.
This package is licensed under the MIT License.