PHP code example of devsrealm / tonics-router-system
1. Go to this page and download the library: Download devsrealm/tonics-router-system library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
devsrealm / tonics-router-system example snippets
use Devsrealm\TonicsRouterSystem\Container\Container;
use Devsrealm\TonicsRouterSystem\Events\OnRequestProcess;
use Devsrealm\TonicsRouterSystem\Handler\Router;
use Devsrealm\TonicsRouterSystem\RequestInput;
use Devsrealm\TonicsRouterSystem\Resolver\RouteResolver;
use Devsrealm\TonicsRouterSystem\Response;
use Devsrealm\TonicsRouterSystem\Route;
use Devsrealm\TonicsRouterSystem\RouteNode;
use Devsrealm\TonicsRouterSystem\RouteTreeGenerator;
use Devsrealm\TonicsRouterSystem\State\RouteTreeGeneratorState;
$onRequestProcess = new OnRequestProcess(
new RouteResolver(
new Container()
),
new Route(
new RouteTreeGenerator(
new RouteTreeGeneratorState(), new RouteNode()
)
)
);
$router = new Router(
$onRequestProcess,
$onRequestProcess->getRouteObject(),
new Response(
$onRequestProcess, new RequestInput()
)
);
$route = $router->getRoute();
$route->get('/', function() {
return 'Welcome To My Home Page';
});
// Once your route is set up, dispatch it (don't forget to do this once all your route is set-up, otherwise, it won't work):
try {
$router->dispatchRequestURL();
} catch (Exception $e) {
// handle error or 404
}
class Authenticated implements TonicsRouterRequestInterceptorInterface
{
/**
* @inheritDoc
*/
public function handle(OnRequestProcess $request): void
{
if (UserData::isAuthenticated() === false){
# If this is for admin, then redirect to admin login
if (str_starts_with($request->getRequestURL(), '/admin')){
redirect(route('admin.login'));
}
# If this is for customer, then redirect to customer login
if (str_starts_with($request->getRequestURL(), '/customer')){
redirect(route('customer.login'));
}
# Else...
SimpleState::displayUnauthorizedErrorMessage();
}
}
}
// For legacy code only (not recommended)
$response = $router->handleWithOutputBuffering($request);
$router->emit($response);
use Devsrealm\TonicsRouterSystem\Handler\Psr7Router;
use Devsrealm\TonicsRouterSystem\Psr7Factory;
// Create a PSR-7 request from globals
$psrRequest = Psr7Factory::createServerRequestFromGlobals();
// Create the router with the PSR-7 request
$router = new Psr7Router($psrRequest);
// Define routes
$router->getRoute()->get('/api/data', function() {
return json_encode(['status' => 'success', 'data' => []]);
});
// Handle the request
$psrResponse = $router->handle($psrRequest);
// Emit the response
$router->emit($psrResponse);
use Devsrealm\TonicsRouterSystem\Handler\Psr7Router;
use Devsrealm\TonicsRouterSystem\Container\Container;
use Devsrealm\TonicsRouterSystem\Resolver\RouteResolver;
use Devsrealm\TonicsRouterSystem\Psr7Factory;
// Create and configure your container
$container = new Container();
// Register all your dependencies
$container->set(DatabaseInterface::class, fn() => new MySQLDatabase());
$container->set(UserRepository::class, fn($c) => new UserRepository($c->get(DatabaseInterface::class)));
// ... more registrations
// Create route resolver with your configured container
$routeResolver = new RouteResolver($container);
// Create PSR-7 request
$psrRequest = Psr7Factory::createServerRequestFromGlobals();
// Create router with custom resolver
$router = new Psr7Router($psrRequest, $routeResolver);
// Now define routes
$router->getRoute()->get('/', [HomeController::class, 'index']);
$router->run();
$router = Psr7Router::create();
// Register only what can't be auto-resolved (primitives, interfaces, etc.)
$router->getContainer()->set(DatabaseInterface::class, function() {
return new MySQLDatabase('localhost', 'mydb', 'user', 'pass');
});
// These classes will be auto-resolved
class EmailService {
// No dependencies - will be auto-created
}
class UserRepository {
// DatabaseInterface must be registered (interface)
public function __construct(private DatabaseInterface $db) {}
}
class UserService {
// UserRepository will be auto-created, EmailService will be auto-created
public function __construct(
private UserRepository $repo,
private EmailService $email
) {}
}
class UserController {
// UserService and all its dependencies will be auto-resolved!
public function __construct(private UserService $service) {}
public function show($id) {
return json_encode($this->service->findById($id));
}
}
// Just register the route - everything else is automatic!
$router->getRoute()->get('/users/:id', [UserController::class, 'show']);
use Devsrealm\TonicsRouterSystem\Adapter\Psr7RequestAdapter;
use Devsrealm\TonicsRouterSystem\Psr7Factory;
$psrRequest = Psr7Factory::createServerRequestFromGlobals();
$requestAdapter = new Psr7RequestAdapter($psrRequest);
// Use it like the traditional RequestInput
$postData = $requestAdapter->fromPost()->all();
$userId = $requestAdapter->fromGet()->retrieve('user_id');
use Devsrealm\TonicsRouterSystem\Adapter\Psr7ResponseAdapter;
use Devsrealm\TonicsRouterSystem\Psr7Factory;
$psrResponse = Psr7Factory::createResponse(200);
$responseAdapter = new Psr7ResponseAdapter($psrResponse);
// Use Tonics-style methods
$responseAdapter->json(['status' => 'success']);
// or
$responseAdapter->redirect('/dashboard');
use Devsrealm\TonicsRouterSystem\Container\Container;
use Devsrealm\TonicsRouterSystem\Events\OnRequestProcess;
use Devsrealm\TonicsRouterSystem\Handler\Router;
use Devsrealm\TonicsRouterSystem\RequestInput;
use Devsrealm\TonicsRouterSystem\Resolver\RouteResolver;
use Devsrealm\TonicsRouterSystem\Response;
use Devsrealm\TonicsRouterSystem\Route;
use Devsrealm\TonicsRouterSystem\RouteNode;
use Devsrealm\TonicsRouterSystem\RouteTreeGenerator;
use Devsrealm\TonicsRouterSystem\State\RouteTreeGeneratorState;
$onRequestProcess = new OnRequestProcess(
new RouteResolver(new Container()),
new Route(
new RouteTreeGenerator(
new RouteTreeGeneratorState(),
new RouteNode()
)
)
);
$router = new Router(
$onRequestProcess,
$onRequestProcess->getRouteObject(),
new Response($onRequestProcess, new RequestInput())
);
// Traditional usage works as always
$route = $router->getRoute();
$route->get('/', function() {
return 'Hello World';
});
$router->dispatchRequestURL();
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;
class UserController
{
public function show(ServerRequestInterface $request, string $id)
{
// Access PSR-7 request
$queryParams = $request->getQueryParams();
$headers = $request->getHeaders();
return "User: $id";
}
}
use Devsrealm\TonicsRouterSystem\Handler\Psr7Router;
use Nyholm\Psr7\Factory\Psr17Factory;
// Create a test request
$factory = new Psr17Factory();
$testRequest = $factory->createServerRequest('GET', '/api/user/123');
// Create router and handle
$router = new Psr7Router($testRequest);
$router->getRoute()->get('/api/user/:id', function($id) {
return json_encode(['id' => $id]);
});
$response = $router->handle($testRequest);
// Assert response
assert($response->getStatusCode() === 200);
assert($response->getHeaderLine('Content-Type') === 'application/json');
namespace App\Controllers;
class HomeController
{
public function index()
{
return 'Welcome to the homepage!';
}
public function about()
{
return 'About us page';
}
}
// Register routes
$route->get('/', [HomeController::class, 'index']);
$route->get('/about', [HomeController::class, 'about']);
namespace App\Controllers;
class PostController
{
public function show($slug)
{
// Fetch post from database
$post = Post::findBySlug($slug);
if (!$post) {
http_response_code(404);
return 'Post not found';
}
return json_encode($post);
}
public function showById($id)
{
$post = Post::find($id);
return json_encode($post);
}
}
// Register routes
$route->get('/posts/:slug', [PostController::class, 'show']);
$route->get('/posts/id/:id', [PostController::class, 'showById']);
namespace App\Controllers;
use App\Services\UserService;
use App\Services\EmailService;
class UserController
{
private UserService $userService;
private EmailService $emailService;
// Dependencies are automatically injected
public function __construct(UserService $userService, EmailService $emailService)
{
$this->userService = $userService;
$this->emailService = $emailService;
}
public function show($id)
{
$user = $this->userService->findById($id);
return json_encode($user);
}
public function sendWelcomeEmail($id)
{
$user = $this->userService->findById($id);
$this->emailService->sendWelcome($user->email);
return json_encode(['message' => 'Email sent']);
}
}
// Register routes
$route->get('/user/:id', [UserController::class, 'show']);
$route->post('/user/:id/welcome', [UserController::class, 'sendWelcomeEmail']);
namespace App\Controllers;
use Devsrealm\TonicsRouterSystem\RequestInput;
class ApiUserController
{
private RequestInput $input;
public function __construct(RequestInput $input)
{
$this->input = $input;
}
// GET /api/users
public function index()
{
$users = User::all();
return json_encode(['users' => $users]);
}
// GET /api/users/:id
public function show($id)
{
$user = User::find($id);
return json_encode(['user' => $user]);
}
// POST /api/users
public function store()
{
$data = $this->input->fromPost();
$name = $data->retrieve('name');
$email = $data->retrieve('email');
$user = User::create(['name' => $name, 'email' => $email]);
http_response_code(201);
return json_encode(['user' => $user]);
}
// PUT /api/users/:id
public function update($id)
{
$data = $this->input->fromPost();
$user = User::find($id);
$user->name = $data->retrieve('name', $user->name);
$user->email = $data->retrieve('email', $user->email);
$user->save();
return json_encode(['user' => $user]);
}
// DELETE /api/users/:id
public function destroy($id)
{
User::find($id)->delete();
return json_encode(['message' => 'User deleted']);
}
}
// Register RESTful routes
$route->get('/api/users', [ApiUserController::class, 'index']);
$route->get('/api/users/:id', [ApiUserController::class, 'show']);
$route->post('/api/users', [ApiUserController::class, 'store']);
$route->put('/api/users/:id', [ApiUserController::class, 'update']);
$route->delete('/api/users/:id', [ApiUserController::class, 'destroy']);
namespace App\Controllers;
use Psr\Http\Message\ServerRequestInterface;
use Devsrealm\TonicsRouterSystem\Adapter\Psr7ResponseAdapter;
class Psr7UserController
{
// Type-hint PSR-7 interfaces
public function show(ServerRequestInterface $request, $id)
{
// Access query parameters
$queryParams = $request->getQueryParams();
$=> $user->email]);
}
return json_encode(['id' => $user->id, 'name' => $user->name]);
}
}
use Devsrealm\TonicsRouterSystem\Handler\Psr7Router;
// 1. Create router
$router = Psr7Router::create();
// 2. Configure container with your dependencies
$container = $router->getContainer();
// Register database
$container->singleton(PDO::class, function() {
return new PDO('mysql:host=localhost;dbname=myapp', 'user', 'pass');
});
// Register repositories
$container->set(UserRepository::class, function($c) {
return new UserRepository($c->get(PDO::class));
});
$container->set(PostRepository::class, function($c) {
return new PostRepository($c->get(PDO::class));
});
// Register services
$container->set(UserService::class, function($c) {
return new UserService(
$c->get(UserRepository::class),
$c->get(EmailService::class)
);
});
$container->set(EmailService::class, function() {
return new EmailService(getenv('SMTP_HOST'), getenv('SMTP_PORT'));
});
// 3. Define your routes
$router->getRoute()->get('/', [HomeController::class, 'index']);
$router->getRoute()->get('/users/:id', [UserController::class, 'show']);
$router->getRoute()->post('/users', [UserController::class, 'store']);
$router->getRoute()->get('/posts/:slug', [PostController::class, 'show']);
// 4. Run the application
$router->run();
// Controller examples
class HomeController {
public function index() {
return json_encode(['message' => 'Welcome to our API']);
}
}
class UserController {
// Dependencies auto-injected via container
public function __construct(
private UserService $userService,
private UserRepository $userRepo
) {}
public function show($id) {
try {
$user = $this->userService->findById($id);
return json_encode(['user' => $user]);
} catch (NotFoundException $e) {
http_response_code(404);
return json_encode(['error' => 'User not found']);
}
}
public function store() {
// Using PSR-7 request in constructor
$data = json_decode(file_get_contents('php://input'), true);
$user = $this->userService->createUser(
$data['name'] ?? '',
$data['email'] ?? ''
);
http_response_code(201);
return json_encode(['user' => $user]);
}
}
class PostController {
public function __construct(private PostRepository $postRepo) {}
public function show($slug) {
$post = $this->postRepo->findBySlug($slug);
if (!$post) {
http_response_code(404);
return json_encode(['error' => 'Post not found']);
}
return json_encode(['post' => $post]);
}
}
// Service layer
class UserService {
public function __construct(
private UserRepository $userRepo,
private EmailService $emailService
) {}
public function findById($id) {
return $this->userRepo->find($id);
}
public function createUser(string $name, string $email) {
$user = $this->userRepo->create(['name' => $name, 'email' => $email]);
$this->emailService->sendWelcome($user->email);
return $user;
}
}
// Repository layer
class UserRepository {
public function __construct(private PDO $db) {}
public function find($id) {
$stmt = $this->db->prepare('SELECT * FROM users WHERE id = ?');
$stmt->execute([$id]);
return $stmt->fetch(PDO::FETCH_OBJ);
}
public function create(array $data) {
$stmt = $this->db->prepare('INSERT INTO users (name, email) VALUES (?, ?)');
$stmt->execute([$data['name'], $data['email']]);
return $this->find($this->db->lastInsertId());
}
}
namespace App\Middleware;
use Devsrealm\TonicsRouterSystem\Events\OnRequestProcess;
use Devsrealm\TonicsRouterSystem\Interfaces\TonicsRouterRequestInterceptorInterface;
class AuthenticationMiddleware implements TonicsRouterRequestInterceptorInterface
{
public function handle(OnRequestProcess $request): void
{
// Check if user is authenticated
if (!isset($_SESSION['user_id'])) {
// Redirect to login page
http_response_code(401);
header('Location: /login');
exit;
}
// If authenticated, continue to next interceptor or controller
}
}
// Usage
$route->get('/dashboard', [DashboardController::class, 'index'], [AuthenticationMiddleware::class]);
namespace App\Middleware;
use Devsrealm\TonicsRouterSystem\Events\OnRequestProcess;
use Devsrealm\TonicsRouterSystem\Interfaces\TonicsRouterRequestInterceptorInterface;
class CorsMiddleware implements TonicsRouterRequestInterceptorInterface
{
public function handle(OnRequestProcess $request): void
{
// Add CORS headers
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Authorization');
// Handle preflight requests
if ($request->getRequestMethod() === 'OPTIONS') {
http_response_code(200);
exit;
}
// Continue to next interceptor or controller
}
}
// Usage on API routes
$route->group('/api', function (Route $route) {
$route->get('/users', [ApiUserController::class, 'index']);
$route->post('/users', [ApiUserController::class, 'store']);
}, [CorsMiddleware::class]);
namespace App\Middleware;
use Devsrealm\TonicsRouterSystem\Events\OnRequestProcess;
use Devsrealm\TonicsRouterSystem\Interfaces\TonicsRouterRequestInterceptorInterface;
class JsonContentTypeMiddleware implements TonicsRouterRequestInterceptorInterface
{
public function handle(OnRequestProcess $request): void
{
$method = $request->getRequestMethod();
// Check Content-Type for POST, PUT, PATCH requests
if (in_array($method, ['POST', 'PUT', 'PATCH'])) {
$contentType = $request->getHeaderByKey('CONTENT_TYPE');
if (strpos($contentType, 'application/json') === false) {
http_response_code(415);
echo json_encode(['error' => 'Content-Type must be application/json']);
exit;
}
}
// Continue to next interceptor or controller
}
}
namespace App\Middleware;
use Devsrealm\TonicsRouterSystem\Events\OnRequestProcess;
use Devsrealm\TonicsRouterSystem\Interfaces\TonicsRouterRequestInterceptorInterface;
class RateLimitMiddleware implements TonicsRouterRequestInterceptorInterface
{
private int $maxRequests = 100;
private int $perMinutes = 1;
public function handle(OnRequestProcess $request): void
{
$ip = $request->getHeaderByKey('REMOTE_ADDR');
$key = "rate_limit:$ip";
// Get current count from cache (Redis, Memcached, etc.)
$count = Cache::get($key, 0);
if ($count >= $this->maxRequests) {
http_response_code(429);
echo json_encode(['error' => 'Too many requests. Please try again later.']);
exit;
}
// Increment counter
Cache::increment($key);
Cache::expire($key, $this->perMinutes * 60);
// Continue to next interceptor or controller
}
}
namespace App\Middleware;
use Devsrealm\TonicsRouterSystem\Events\OnRequestProcess;
use Devsrealm\TonicsRouterSystem\Interfaces\TonicsRouterRequestInterceptorInterface;
class LoggingMiddleware implements TonicsRouterRequestInterceptorInterface
{
public function handle(OnRequestProcess $request): void
{
$method = $request->getRequestMethod();
$url = $request->getRequestURL();
$ip = $request->getHeaderByKey('REMOTE_ADDR');
$userAgent = $request->getUserAgent();
// Log the request
error_log(sprintf(
"[%s] %s %s from %s - %s",
date('Y-m-d H:i:s'),
$method,
$url,
$ip,
$userAgent
));
// Continue to next interceptor or controller
}
}
// Apply to all routes
$route->group('/', function (Route $route) {
// All your routes here
}, [LoggingMiddleware::class]);
namespace App\Middleware;
// Chain multiple interceptors
$route->group('/admin', function (Route $route) {
$route->get('/dashboard', [AdminController::class, 'dashboard']);
$route->get('/users', [AdminController::class, 'users']);
$route->post('/users', [AdminController::class, 'createUser']);
}, [
LoggingMiddleware::class, // First: Log the request
AuthenticationMiddleware::class, // Second: Check if user is logged in
AdminAuthorizationMiddleware::class, // Third: Check if user is admin
CsrfMiddleware::class // Fourth: Validate CSRF token
]);
// Good: Focused controller
class UserController {
public function show($id) { /* ... */ }
public function update($id) { /* ... */ }
}
class UserProfileController {
public function show($id) { /* ... */ }
public function updateAvatar($id) { /* ... */ }
}
// Bad: Too many responsibilities
class UserController {
public function show($id) { /* ... */ }
public function updateProfile($id) { /* ... */ }
public function uploadAvatar($id) { /* ... */ }
public function sendEmail($id) { /* ... */ }
public function generateReport($id) { /* ... */ }
// ... 50 more methods
}
public function show($id) {
$user = User::find($id);
return json_encode($user); // ✅ Return
}
public function show($id) {
$user = User::find($id);
echo json_encode($user); // ❌ Echo (not PSR-7 compliant)
}
class UserController {
private UserRepository $userRepo;
public function __construct(UserRepository $userRepo) {
$this->userRepo = $userRepo; // ✅ Injected
}
public function show($id) {
return json_encode($this->userRepo->find($id));
}
}
class UserController {
public function show($id) {
$userRepo = new UserRepository(); // ❌ Tight coupling
return json_encode($userRepo->find($id));
}
}
// Good: Single responsibility
class AuthenticationMiddleware implements TonicsRouterRequestInterceptorInterface {
public function handle(OnRequestProcess $request): void {
// Only handles authentication
if (!$this->isAuthenticated()) {
$this->redirectToLogin();
}
}
}
$route->group('/admin', function (Route $route) {
// Routes here
}, [
AuthenticationMiddleware::class, // Check if logged in
AdminAuthorizationMiddleware::class, // Check if admin
CsrfMiddleware::class // Validate CSRF
]);
// Bad: Does too much
class MegaMiddleware implements TonicsRouterRequestInterceptorInterface {
public function handle(OnRequestProcess $request): void {
// Authentication
// Authorization
// CSRF validation
// Rate limiting
// Logging
// ... everything in one class
}
}
// Good: Organized by feature
$route->group('/api/v1', function (Route $route) {
$route->group('/users', function (Route $route) {
$route->get('', [UserController::class, 'index']);
$route->get(':id', [UserController::class, 'show']);
$route->post('', [UserController::class, 'store']);
});
$route->group('/posts', function (Route $route) {
$route->get('', [PostController::class, 'index']);
$route->get(':id', [PostController::class, 'show']);
});
}, [CorsMiddleware::class, AuthMiddleware::class]);