henriquebs0/router

dev-main 2022-01-29 21:34 UTC

This package is auto-updated.

Last update: 2024-05-28 21:17:05 UTC


README

PHP component to control your application's routes.

Componente PHP para o controle de rotas de sua aplicação.

Installation

Composer

composer require henriquebs0/router dev-main

Routes

To start managing routes, just instantiate an object of the Router(string $baseUri = '/') class in a central point of your application where all requests pass (Ex: the file index.php), add the routes and at the end call the resolve() method.

htaccess

RewriteEngine On

# ROUTER URL Rewrite
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteRule ^(.*)$ index.php?/$1 [L,QSA]

index.php

<?php

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

use HenriqueBS0\Router\Router;

/**
 * Instantiating the object
 */
$router = new Router();

/**
 * Adding a route to the '/' path
 */
$router->get('/', function() {
    echo 'Hello World!';
});

/**
 * Resolves the process and forwards to the route
 */
$router->resolve();

Adding Routes

To add routes there are five methods that are directly related to HTTP methods, namely:

  • get($path, $callback, $middlewaresClasses): void

  • post($path, $callback, $middlewaresClasses): void

  • put($path, $callback, $middlewaresClasses): void

  • patch($path, $callback, $middlewaresClasses): void

  • delete($path, $callback, $middlewaresClasses): void

    • string $path: Path that will be accessed.
    • callable|array $callback: Function to be performed.
    • array $middlewaresClasses: Middleware classes.
<form method="POST">
    <label for="_method">Method</label>
    <select name="_method" id="_method">
        <option value="GET">GET</option>
        <option value="POST">POST</option>
        <option value="PUT">PUT</option>
        <option value="PATCH">PATCH</option>
        <option value="DELETE">DELETE</option>
    </select>
    <input type="submit" value="Send">
</form>
<?php

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

use HenriqueBS0\Router\Router;

class Controller {
    public function get() {
        echo "GET";
    }

    public function post() {
        echo "POST";
    }

    public function put() {
        echo "PUT";
    }

    public function patch() {
        echo "PATCH";
    }

    public function delete() {
        echo "DELETE";
    }
}

$router = new Router();

$router->get('/', [Controller::class, 'get']);
$router->post('/', [Controller::class, 'post']);
$router->put('/', [Controller::class, 'put']);
$router->patch('/', [Controller::class, 'patch']);
$router->delete('/', [Controller::class, 'delete']);

$router->resolve();

Note that there is a reserved parameter _method, this is because HTML5 forms only support the GET and POST methods.

Parameters URL

To inform that a parameter is expected, enclose the name of this parameter in curly braces, these will be passed in order to the route callback.

<?php

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

use HenriqueBS0\Router\Router;

class Controller {
    public function user($id) {
        echo "User id - {$id}";
    }
}

$router = new Router();

/**
 * Expect to receive the 'id' parameter
 */
$router->get('/user/{id}', [Controller::class, 'user']);

$router->resolve();

Group

To facilitate the process of informing paths there is the method group(string $group) that sets a base path for all the next informed routes. As is the previous example using this feature.

<?php

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

use HenriqueBS0\Router\Router;

class Controller {
    public function user($id) {
        echo "User id - {$id}";
    }
}

$router = new Router();

$router->group('/user');

$router->get('/{id}', [Controller::class, 'user']);

$router->resolve();

Not Found

When the URL accessed does not match any route a default method is triggered, it sets the request status to 404, and then prints this value, to change this behavior there is the method setNotFound(callable|array $callback).

<?php

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

use HenriqueBS0\Router\Router;

$router = new Router();
$router->setNotFound(function() {
    echo 'Not Found.';
});
$router->resolve();

Middlewares

Middlewares are a way to inspect the requests that come to your application. To create a middleware just create a class that extends Middleware.

<?php

use HenriqueBS0\Router\Middleware;

class MiddlewareExample extends Middleware {
    public function checks(): bool
    {
        return true;
    }

    public function invalidated(): void
    {
        echo 'Not authorized';
    }
}

The above class is composed of two methods, checks() which checks if the request is authorized and invalidated() which is executed when the request is not authorized (when checks() returns false).

Associating Middlewares

A middleware can be associated directly with a route, or be associated in a general way, after adding a middleware in a general way, all the routes added after will take it into account.

<?php

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

use HenriqueBS0\Router\Middleware;
use HenriqueBS0\Router\Router;

class MiddlwareGeneralOne extends Middleware {}
class MiddlwareGeneralTwo extends Middleware {}

class MiddlwareRouteOne extends Middleware {}
class MiddlwareRouteTwo extends Middleware {}

$router = new Router();

/**
 * Linking middleware in general
 * All routes added after this action will consider middlewares
 * 'MiddlwareGeneralOne' and 'MiddlwareGeneralTwo'
 */
$router->setMiddlewares([
    MiddlwareGeneralOne::class,
    MiddlwareGeneralTwo::class
]);

/**
 * Binding middleware specifically to route
 */
$router->get('/', function() {
    echo 'Hello World';
}, [MiddlwareRouteOne::class, MiddlwareRouteTwo::class]);

$router->resolve();

Methods for dealing with associated middleware in general

  • setMiddlewares(array $middlewaresClasses): void
  • addMiddleware(string $middlewareClass): void
  • clearMiddlewares(): void
<?php

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

use HenriqueBS0\Router\Middleware;
use HenriqueBS0\Router\Router;

class MiddlwareOne extends Middleware {}
class MiddlwareTwo extends Middleware {}
class MiddlwareThree extends Middleware {}
class MiddlwareFour extends Middleware {}

$router = new Router();

/**
 * Define that the middlewares applied will be
 * 'MiddlwareOne' and 'MiddlwareTwo'
 */
$router->setMiddlewares([
    MiddlwareOne::class,
    MiddlwareTwo::class
]);

/**
 * Clear all general middleware,
 * ie no middleware will be applied
 */

$router->clearMiddlewares();

/**
 * Add general middleware 'MiddlwareThree' and 'MiddlwareFour'
 */

 $router->addMiddleware(MiddlwareThree::class);
 $router->addMiddleware(MiddlwareFour::class);

 /**
  * According to flow the 'MiddlwareThree' and 'MiddlwareFour'
  * middleware will be linked to the route
  */
$router->get('/', function() {
    echo 'Hello World';
});

$router->resolve();

Route Groups

To make the code more organized, you can separate the routes into classes and then add these to the instance of the Router class with the addRoutesGroup(string $routesGroupClass) method, these grouping classes of routes must extend the RoutesGroup class.

<?php

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

use HenriqueBS0\Router\Middleware;
use HenriqueBS0\Router\Router;
use HenriqueBS0\Router\RoutesGroup;

class MiddlewareGeneral extends Middleware {};
class MiddlewareRoutesUser extends Middleware{};

class ControllerUser {
    public function userGet($id) {
        echo "User - {$id} | GET";
    }

    public function userPost() {
        echo 'User | POST';
    }

    public function userPut($id) {
        echo "User - {$id} | PUT";
    }

    public function userPatch($id) {
        echo "User - {$id} | PATCH";
    }

    public function userDelete($id) {
        echo "User - {$id} | DELETE";
    }
}

/**
 * Class with route group
 */

class RoutesUser extends RoutesGroup {

    /**
     * Reserved method for adding routes
     */
    protected function setRoutes(): void
    {
        $this->group('/user');

        $this->setMiddlewares([MiddlewareRoutesUser::class]);

        $this->get('/{id}', [ControllerUser::class, 'userGet']);
        $this->post('/', [ControllerUser::class, 'userPost']);
        $this->put('/{id}', [ControllerUser::class, 'userPut']);
        $this->patch('/{id}', [ControllerUser::class, 'userPatch']);
        $this->delete('/{id}', [ControllerUser::class, 'userDelete']);
    }
}

$router = new Router();

$router->get('/', function() {
    echo 'Hello World!';
});

/**
 * Adding general middleware
 */
$router->addMiddleware(MiddlewareGeneral::class);

/**
 * Adding a generic group
 */
$router->group('/generic');

/**
 * Adding route group
 */
$router->addRoutesGroup(RoutesUser::class);

$router->resolve();

Note that classes that extend RoutesGroup have the reserved method setRoutes() where the routes must be defined. The Router class shares methods with the RoutesGroup class that have the same purpose, they are:

  • get($path, $callback, $middlewaresClasses): void
  • post($path, $callback, $middlewaresClasses): void
  • put($path, $callback, $middlewaresClasses): void
  • patch($path, $callback, $middlewaresClasses): void
  • delete($path, $callback, $middlewaresClasses): void
  • group(string $group): void
  • setMiddlewares(array $middlewaresClasses): void
  • addMiddleware(string $middlewareClass): void
  • clearMiddlewares(): void

External general middleware like the example MiddlewareGeneral is associated with the route group.

The group method in the scope of the setRoutes method does not interfere with the group method of the Router class instance, the opposite too does not occur.

Example project: Link Pack

License

The MIT License (MIT). Please see License file for more information.