simple-php-router

repository·master·Indexed 20 days ago

https://github.com/skipperbent/simple-php-router

A fast, lightweight PHP router inspired by Laravel's routing syntax. It supports various HTTP verbs (GET, POST, PUT, PATCH, DELETE), named routes, route groups, middleware, CSRF protection, and regular expression constraints for parameters. It is designed for easy integration into projects without a full framework and requires PHP 7.1 or greater (with JSON extension enabled), though versions 3.x and below support PHP 5.5+.

Tokens
19.7K
Snippets
76
Records
85
Agent score
68%

What's inside simple-php-router

  1. Overview of simple-router features

    master

    simple-router is a lightweight PHP router inspired by Laravel. Key features include:

    • HTTP Verbs: Support for GET, POST, PUT, PATCH, UPDATE, DELETE, and custom multiple verbs.
    • Route Management: Named routes, route groups, namespaces, route prefixes, and sub-domain routing.
    • Parameter Handling: Regular expression constraints and optional parameters.
    • Security & Control: Middleware, CSRF protection, and IP-based restrictions.
    • Utilities: Input manager for GET, POST, and FILE values, and custom boot managers for URL rewriting.
  2. Use route groups for shared attributes

    master

    Route groups allow you to apply shared attributes like middleware, namespace, prefix, or domain to multiple routes at once using SimpleRouter::group().

    • Middleware: Executes specified middleware for all routes in the group.
    • Namespace: Prepends a PHP namespace to relative controller callbacks.
    • Prefix: Adds a URL prefix to all routes in the group.
    • Domain: Handles subdomain routing (e.g., {account}.myapp.com).
    // Middleware and Prefix example
    SimpleRouter::group(['middleware' => \Demo\Middleware\Auth::class, 'prefix' => '/admin'], function () {
        SimpleRouter::get('/users', function () {
            // Matches /admin/users and uses Auth middleware
        });
    });
    
    // Subdomain example
    SimpleRouter::group(['domain' => '{account}.myapp.com'], function () {
        SimpleRouter::get('/user/{id}', function ($account, $id) {
            // ...
        });
    });
  3. Use partial groups for conditional routing

    master

    A partialGroup is only rendered once its URL pattern has matched. This is useful for loading dynamic routes (like plugin routes) only when a specific URL structure is requested.

    Warning: Because these routes are only registered after a match, the url() helper may not be able to find or generate URLs for routes inside a partial group until that group has been matched.

    SimpleRouter::partialGroup('/plugin/{name}', function ($plugin) {
        // Routes added here are only available if /plugin/{name} matches
    });
  4. Use the `url()` helper to manage routes and URLs

    master

    The url() helper function is a shortcut to retrieve URLs for defined routes or manipulate the current URL. It returns a Url object, which behaves like a string when rendered (e.g., in templates) but provides powerful methods for inspection and manipulation.

    Get the current URL

    To get the current relative URL, call the helper without arguments:

    url(); // returns current path, e.g., '/current-url'

    Retrieve URLs by name

    You can generate URLs for specific routes using their assigned names or controller/class patterns.

    Single Route by Name: If a route is named using the as option, pass the name and any required parameters.

    SimpleRouter::get('/product-view/{id}', 'ProductsController@show', ['as' => 'product']);
    
    // With path parameters and query strings
    url('product', ['id' => 22], ['category' => 'shoes']); // /product-view/22/?category=shoes
    
    // Only query strings
    url('product', null, ['category' => 'shoes']); // /product-view/?category=shoes

    Controller Routes: If using SimpleRouter::controller(), you can target specific methods.

    SimpleRouter::controller('/images', ImagesController::class, ['as' => 'picture']);
    
    // Using @ syntax
    url('picture@getView', null, ['category' => 'shoes']);
    
    // Using method name as second argument
    url('picture', 'getView', ['category' => 'shoes']);
    
    // Using only the method name
    url('picture', 'view');

    Class-based URLs: You can reference routes directly via their controller class and method.

    SimpleRouter::get('/product-view/{id}', 'ProductsController@show', ['as' => 'product']);
    url('ProductsController@show', ['id' => 22]);

    REST/Resource URLs: When using SimpleRouter::resource(), standard RESTful names are available.

    SimpleRouter::resource('/phones', PhonesController::class);
    
    url('phones');        // /phones/
    url('phones.index');  // /phones/
    url('phones.create'); // /phones/create/
    url('phones.edit');   // /phones/edit/
    // Example of generating a named route URL
    SimpleRouter::get('/product-view/{id}', 'ProductsController@show', ['as' => 'product']);
    url('product', ['id' => 22], ['category' => 'shoes']);
  5. Load routes dynamically using IRouterBootManager

    master

    To load routes from a database or external file, implement the IRouterBootManager interface. The boot() method is called before routes are loaded, allowing you to intercept the request and rewrite the URL.

    use Pecee\SimpleRouter\IRouterBootManager;
    use Pecee\SimpleRouter\Router;
    
    class CustomRouterRules implements IRouterBootManager 
    {
        public function boot(Router $router, \Pecee\Http\Request $request): void
        {
            $rewriteRules = [
                '/my-cat-is-beatiful' => '/article/view/1',
                '/horses-are-great'   => '/article/view/2',
            ];
    
            foreach($rewriteRules as $url => $rule) {
                if($request->getUrl()->contains($url)) {
                    $request->setRewriteUrl($rule);
                }
            }
        }
    }
    
    // Register in routes.php
    SimpleRouter::addBootManager(new CustomRouterRules());
  6. Manipulate URLs and query strings with the `Url` object

    master

    The url() helper returns a Url object (from the Pecee\Http\Url class) that allows for advanced inspection and modification of the current URL.

    Query String Manipulation

    You can add or remove query parameters easily.

    Add parameters:

    // Appends ?q=cars to the current URL
    url(null, null, ['q' => 'cars']);

    Remove parameters:

    // Removes the 'q' parameter while keeping others
    $url = url()->removeParam('q');

    Inspecting the URL

    Use methods like contains() to check for specific path segments or getParam() to retrieve values.

    // Check if current URL contains '/api'
    if(url()->contains('/api')) { /* ... */ }
    
    // Get a specific query parameter
    $id = url()->getParam('id');
    
    // Get the absolute URL (including host)
    $absoluteUrl = url()->getAbsoluteUrl();
    // Check if current URL contains a segment
    if(url()->contains('/api')) {
        // ...
    }
    
    // Remove a specific parameter
    $url = url()->removeParam('q');
  7. Use Middlewares to intercept requests

    master

    Middlewares are classes that execute before a route is rendered. They must implement the IMiddleware interface. Use them for authentication, logging, or setting request-specific parameters.

    namespace Demo\Middlewares;
    
    use Pecee\Http\Middleware\IMiddleware;
    use Pecee\Http\Request;
    
    class CustomMiddleware implements IMiddleware {
        public function handle(Request $request): void 
        {
            // Example: Authenticate user and attach to request
            $request->user = User::authenticate();
    
            if($request->user === null) {
                $request->setRewriteUrl(url('user.login'));
            }
        }
    }
    namespace Demo\Middlewares;
    
    use Pecee\Http\Middleware\IMiddleware;
    use Pecee\Http\Request;
    
    class CustomMiddleware implements IMiddleware {
        public function handle(Request $request): void 
        {
            $request->user = User::authenticate();
            if($request->user === null) {
                $request->setRewriteUrl(url('user.login'));
            }
        }
    }
  8. Restrict access by IP using IpRestrictAccess middleware

    master

    Extend the IpRestrictAccess middleware to whitelist or blacklist specific IP addresses. You can use * to represent an IP range.

    use \Pecee\Http\Middleware\IpRestrictAccess;
    
    class IpBlockerMiddleware extends IpRestrictAccess 
    {
        protected $ipBlacklist = [
            '5.5.5.5',
            '8.8.*',
        ];
    
        protected $ipWhitelist = [
            '8.8.2.2',
        ];
    }
  9. Set a custom base path for all routes

    master

    You can set a custom base path for all routes by registering an EventHandler for the EVENT_ADD_ROUTE event. This allows you to prepend a path to ILoadableRoute or IGroupRoute instances.

    $basePath = '/basepath';
    
    $eventHandler = new EventHandler();
    $eventHandler->register(EventHandler::EVENT_ADD_ROUTE, function(EventArgument $event) use($basePath) {
    
        $route = $event->route;
    
        // Skip routes added by group as these will inherit the url
        if(!$event->isSubRoute) {
            return;
        }
        
        switch (true) {
            case $route instanceof ILoadableRoute:
                $route->prependUrl($basePath);
                break;
            case $route instanceof IGroupRoute:
                $route->prependPrefix($basePath);
                break;
        }
    });
    
    SimpleRouter::addEventHandler($eventHandler);