Skip to content

Commit

Permalink
Request method wrappers (#12)
Browse files Browse the repository at this point in the history
Add new method wrappers:

* Add a wrapper for adding `get` endpoint
* Add a wrapper for adding `post` endpoint
* Add a wrapper for adding `put` endpoint
* Add a wrapper for adding `patch` endpoint
* Add a wrapper for adding `delete` endpoint

Sample: 

```php
$routes
    ->prefix("/test")
    ->middleware(['decode_token'])
    ->route("/t0", function(Request $request){})
    ->get("/t1", function (){})
    ->post("/t2", function (){})
    ->put("/t3", function (){})
    ->patch("/t4", function (){})
    ->delete("/t5", function (){})
    ->save();
```

Which is equivalent to doing: 

```php
$routes
    ->prefix("/test")
    ->middleware(['decode_token'])
    ->route("/t0", function(Request $request){})
    ->route("/t1", function (){}, [Routes::GET])
    ->route("/t2", function (){}, [Routes::POST])
    ->route("/t3", function (){}, [Routes::PATCH])
    ->route("/t4", function (){}, [Routes::PUT])
    ->route("/t5", function (){}, [Routes::DELETE])
    ->save();
```
  • Loading branch information
gigili authored Oct 1, 2021
1 parent 6f037d0 commit aec1a91
Show file tree
Hide file tree
Showing 4 changed files with 171 additions and 31 deletions.
33 changes: 29 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@ try {
->status(200, "OK")
->send(["message" => "Welcome"]);
});

$routes->route('/', function (Request $request) {
$request
->status(200, "OK")
->send(["message" => "Welcome"]);
})->save();

$routes->route();
} catch (RouteNotFoundException $ex) {
Expand All @@ -80,20 +86,39 @@ try {

## Examples

Using chained method to wrap multiple routes with a same middleware or a route prefix
### Chained routes

Using chained method to wrap multiple routes with a same middleware or a route prefix When using chained method either
use `save()` or `add()` as the last method to indicate the end of a chain;

**NOTE**
Both the `save` and `add` methods **CAN'T** be chained on, so they need to be the last one in the chain.

```php
$routes
->prefix('/user') // all the routes add will have the /user prefix
->middleware([ 'verify_token' ]) // all the routes added will have the verify_token middelware applied
->middleware([ 'verify_token' ]) // all the routes added will have the verify_token middleware applied
->route('/', [ HomeController::class, 'getUsers' ], Routes::GET)
->route('/', [ HomeController::class, 'addUser' ], Routes::POST)
->route('/', [ HomeController::class, 'updateUser' ], Routes::PATCH)
->route('/', [ HomeController::class, 'replaceUser' ], Routes::PUT)
->add('/test', [ HomeController::class, 'deleteUser' ], Routes::DELETE);
```

Dynamic routes example:
```php
$routes
->prefix("/test")
->middleware(['decode_token'])
->route("/t0", function(Request $request){})
->get("/t1", function (){})
->post("/t2", function (){})
->put("/t3", function (){})
->patch("/t4", function (){})
->delete("/t5", function (){})
->save();
```

### Dynamic routes example

```php
$routes->add('/test/{int:userID}-{username}/{float:amount}/{bool:valid}', function (
Expand All @@ -107,7 +132,7 @@ $routes->add('/test/{int:userID}-{username}/{float:amount}/{bool:valid}', functi
});
```

For more example look in the [sample folder](/sample).
For more example look in the [sample folder](/sample) `index.php` file

## Documentation

Expand Down
6 changes: 5 additions & 1 deletion Request.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,11 @@ public function send(string|array|object $output) {
echo json_encode($output);
}


/**
* Private method used for parsing request body data for PUT and PATCH requests
*
* @return array Return an array of request body data
*/
private function parse_patch_and_put_request_data() : array {

/* PUT data comes in on the stdin stream */
Expand Down
112 changes: 96 additions & 16 deletions Routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ public function __construct()
*
* @param string $prefix Prefix to be added to all the routes in that chain.
*
* @return Routes Returns an instance of it self so that other methods could be chained onto it
* @return Routes Returns an instance of itself so that other methods could be chained onto it
*/
public function prefix(string $prefix = ''): self
{
Expand All @@ -99,7 +99,7 @@ public function prefix(string $prefix = ''): self
*
* @param array $data List of middlewares to be executed before the routes
*
* @return Routes Returns an instance of it self so that other methods could be chained onto it
* @return Routes Returns an instance of itself so that other methods could be chained onto it
*/
public function middleware(array $data): self
{
Expand All @@ -110,9 +110,16 @@ public function middleware(array $data): self
/**
* Method used to handle execution of routes and middlewares
*
* @param string $path Path for the route
* @param callable|array|string|null $callback Callback method, an anonymous function or a class and method name to be executed
* @param string|array $methods Allowed request method(s) (GET, POST, PUT...)
*
* @return Routes Returns an instance of itself so that other methods could be chained onto it
*/
public function route(string $path, callable|array|string $callback, string|array $methods = self::GET): self
{
public function route(string $path,
callable|array|string|null $callback,
string|array $methods = self::GET
) : self {
if ( is_string($methods) ) $methods = [ $methods ];

if ( !empty($this->prefix) ) $path = $this->prefix . $path; // Prepend prefix to routes
Expand Down Expand Up @@ -143,6 +150,7 @@ public function route(string $path, callable|array|string $callback, string|arra
}
}

$this->save(false);
return $this;
}

Expand All @@ -154,10 +162,16 @@ public function route(string $path, callable|array|string $callback, string|arra
* @param string|array|null $methods Allowed request method(s) (GET, POST, PUT...)
*
*/
public function add(string $path = '', callable|array|string|null $callback = NULL, string|array|null $methods = self::GET)
{
public function add(
string $path = '',
callable|array|string|null $callback = NULL,
string|array|null $methods = self::GET
) {
$this->route($path, $callback, $methods);
$this->save();
}

public function save(bool $cleanData = true) {
foreach ( $this->tmpRoutes as $method => $route ) {
if ( !isset($this->routes[$method]) ) $this->routes[$method] = [];
$path = array_key_first($route);
Expand All @@ -175,9 +189,11 @@ public function add(string $path = '', callable|array|string|null $callback = NU
$this->routes[$method] = array_merge($this->routes[$method], $route);
}

$this->prefix = '';
$this->middlewares = [];
$this->tmpRoutes = [];
if ( $cleanData ) {
$this->prefix = '';
$this->middlewares = [];
$this->tmpRoutes = [];
}
}

/**
Expand All @@ -186,8 +202,7 @@ public function add(string $path = '', callable|array|string|null $callback = NU
* @throws RouteNotFoundException When the route was not found
* @throws CallbackNotFound When the callback for the route was not found
*/
public function handle()
{
public function handle() {
$path = $this->getPath();
$method = $_SERVER['REQUEST_METHOD'] ?? 'GET';

Expand Down Expand Up @@ -245,7 +260,7 @@ public function handle()

if ( ( is_string($callback) && class_exists($callback) ) || is_array($callback) ) {
$controller = is_string($callback) ? new $callback : new $callback[0]; // make a new instance of a controller class
$fn = is_string($callback) ? 'index' : $callback[1] ?? 'index'; // get the method to be execute or fallback to index method
$fn = is_string($callback) ? 'index' : $callback[1] ?? 'index'; // get the method to be executed or fallback to index method
$callback = [ $controller, $fn ];
}

Expand All @@ -266,9 +281,10 @@ public function handle()
}

/**
* Private method used to fetch the arguments of the routs callback methods
* Private method used to fetch the arguments of the route's callback methods
*
* @param object|array|string $func
*
* @return array|null Returns a list of arguments for a method or null on error
*/
private function get_all_arguments(object|array|string $func): array|null
Expand Down Expand Up @@ -302,7 +318,7 @@ private function get_all_arguments(object|array|string $func): array|null
}

/**
* Method which executes each specified middleware before the routes callback is executed
* Method which executes each specified middleware before the route's callback is executed
*
* @param array $data List of middlewares to be executed before accessing the endpoint
*
Expand Down Expand Up @@ -341,8 +357,72 @@ private function getPath(): string
*
* @return array
*/
public function getRoutes(): array
{
public function getRoutes() : array {
return $this->routes;
}

/**
* Wrapper method used for adding new GET routes
*
* @param string $path Path for the route
* @param callable|array|string|null $callback Callback method, an anonymous function or a class and method name to be executed
*
* @return Routes Returns an instance of itself so that other methods could be chained onto it
*/
public function get(string $path, callable|array|string|null $callback = NULL) : self {
$this->route($path, $callback, [ self::GET ]);
return $this;
}

/**
* Wrapper method used for adding new POST routes
*
* @param string $path Path for the route
* @param callable|array|string|null $callback Callback method, an anonymous function or a class and method name to be executed
*
* @return Routes Returns an instance of itself so that other methods could be chained onto it
*/
public function post(string $path, callable|array|string|null $callback = NULL) : self {
$this->route($path, $callback, [ self::POST ]);
return $this;
}

/**
* Wrapper method used for adding new POST routes
*
* @param string $path Path for the route
* @param callable|array|string|null $callback Callback method, an anonymous function or a class and method name to be executed
*
* @return Routes Returns an instance of itself so that other methods could be chained onto it
*/
public function put(string $path, callable|array|string|null $callback = NULL) : self {
$this->route($path, $callback, [ self::PUT ]);
return $this;
}

/**
* Wrapper method used for adding new POS routes
*
* @param string $path Path for the route
* @param callable|array|string|null $callback Callback method, an anonymous function or a class and method name to be executed
*
* @return Routes Returns an instance of itself so that other methods could be chained onto it
*/
public function patch(string $path, callable|array|string|null $callback = NULL) : self {
$this->route($path, $callback, [ self::PATCH ]);
return $this;
}

/**
* Wrapper method used for adding new POST routes
*
* @param string $path Path for the route
* @param callable|array|string|null $callback Callback method, an anonymous function or a class and method name to be executed
*
* @return Routes Returns an instance of itself so that other methods could be chained onto it
*/
public function delete(string $path, callable|array|string|null $callback = NULL) : self {
$this->route($path, $callback, [ self::DELETE ]);
return $this;
}
}
51 changes: 41 additions & 10 deletions sample/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,25 @@
$routes = new Routes();
try {

// When using chained method either use `save()` or `add()` method at the end to indicate an end of chain
$routes
->prefix("/test")
->middleware([ 'decode_token' ])
->get("/t1", function () { })
->get("/t2", function () { })
->get("/t3", function () { })
->save();

$routes->add('/', function (Request $request) {
echo json_encode([ 'message' => 'Hello World' ]);
});

$routes->add('/test', function (Request $request) {
$request
->status(200, 'OK')
->send([ 'message' => 'Welcome' ]);
});

$routes
->prefix('/user')
->middleware([ 'verify_token' ])
Expand All @@ -31,26 +46,42 @@
->route('/', [ HomeController::class, 'replaceUser' ], Routes::PUT)
->add('/test', [ HomeController::class, 'deleteUser' ], Routes::DELETE);

$routes->add('/test', function (Request $request) {
$request
->status(200, 'OK')
->send([ 'message' => 'Welcome' ]);
});

$routes->add('/test', function () {
}, [ Routes::PATCH, Routes::POST ]);

$routes->get("/test-get", function () {
echo "Hello from test-get";
});

$routes->post("/test-post", function () {
echo "Hello from test-post";
});

$routes->put("/test-put", function () {
echo "Hello from test-put";
});

$routes->patch("/test-patch", function () {
echo "Hello from test-patch";
});

$routes->delete("/test-delete", function () {
echo "Hello from test-delete";
});

$routes->add('/test/{int:userID}-{username}/{float:amount}/{bool:valid}', function (
Request $request,
int $userID,
string $username,
float $amount,
bool $valid
int $userID,
string $username,
float $amount,
bool $valid
) {
echo 'Dynamic route here';
});

$routes->add('/test/{int:userID}-{username}/{float:amount}/{bool:valid}', [ HomeController::class, 'test' ]); # It works like this also
$routes->add('/test/{int:userID}-{username}/{float:amount}/{bool:valid}',
[ HomeController::class, 'test' ]); # It works like this also

$routes
->middleware([
Expand Down

0 comments on commit aec1a91

Please sign in to comment.