Init
This commit is contained in:
commit
d60e072010
13
LICENSE
Normal file
13
LICENSE
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||||
|
Version 2, December 2004
|
||||||
|
|
||||||
|
Copyright (C) 2004 Whomst Ever
|
||||||
|
|
||||||
|
Everyone is permitted to copy and distribute verbatim or modified
|
||||||
|
copies of this license document, and changing it is allowed as long
|
||||||
|
as the name is changed.
|
||||||
|
|
||||||
|
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. You just DO WHAT THE FUCK YOU WANT TO.
|
37
README.md
Normal file
37
README.md
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
# Route
|
||||||
|
|
||||||
|
Minimal PHP Router
|
||||||
|
|
||||||
|
# Installation
|
||||||
|
|
||||||
|
## Composer
|
||||||
|
|
||||||
|
Composer needs to know where to locate the package. Let's add the repository to your project by declaring it in the `composer.json` file.
|
||||||
|
```JSON
|
||||||
|
{
|
||||||
|
"repositories": [
|
||||||
|
{
|
||||||
|
"type": "vcs",
|
||||||
|
"url": "https://git.willy.club/WillySoft/Route"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"require": {
|
||||||
|
"willysoft/route": "dev-master"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
Fetch the package by running
|
||||||
|
|
||||||
|
composer install
|
||||||
|
|
||||||
|
# Usage
|
||||||
|
|
||||||
|
When using a production web server such as Nginx you will have to tell it to rewrite requests that don't point to a local file, such as they can be forwarded to your front controller which in this case is `public/index.php`.
|
||||||
|
|
||||||
|
With PHP already configured, add this to the server block of your configuration to make requests that don't match a file on your server to be sent to your front controller and begin routing.
|
||||||
|
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ /index.php?$query_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
See `example.php` and add it to your `public/index.php` file. It will act as the front controller.
|
88
Route.php
Normal file
88
Route.php
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace WillySoft;
|
||||||
|
|
||||||
|
abstract class Route
|
||||||
|
{
|
||||||
|
static $prefix = '';
|
||||||
|
static $groups = [[]];
|
||||||
|
|
||||||
|
static function match(string $methods, string $uri, callable $callback)
|
||||||
|
{
|
||||||
|
if (!in_array(
|
||||||
|
$_SERVER['REQUEST_METHOD'],
|
||||||
|
array_map(strtoupper(...), explode('|', $methods))
|
||||||
|
)) return;
|
||||||
|
|
||||||
|
$request_uri_parts = explode('/', urldecode(
|
||||||
|
strtok($_SERVER['REQUEST_URI'], '?')
|
||||||
|
));
|
||||||
|
$uri_parts = explode('/', self::$prefix . $uri);
|
||||||
|
$callback_args = [];
|
||||||
|
for ($i = 0; $i < count($uri_parts); $i++) {
|
||||||
|
if ($uri_parts[$i] === '')
|
||||||
|
continue;
|
||||||
|
if ($uri_parts[$i][0] !== '$')
|
||||||
|
continue;
|
||||||
|
if (!isset($request_uri_parts[$i]))
|
||||||
|
return;
|
||||||
|
if (
|
||||||
|
$uri_parts[$i][-1] !== '?'
|
||||||
|
&& $request_uri_parts[$i] === ''
|
||||||
|
) return;
|
||||||
|
if ($request_uri_parts[$i] !== '')
|
||||||
|
array_push($callback_args, $request_uri_parts[$i]);
|
||||||
|
$request_uri_parts[$i] = $uri_parts[$i];
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
implode('/', $uri_parts)
|
||||||
|
!== implode('/', $request_uri_parts)
|
||||||
|
) return;
|
||||||
|
|
||||||
|
foreach (self::$groups as $middlewares) {
|
||||||
|
foreach ($middlewares as $middleware) {
|
||||||
|
$middleware();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$callback(...$callback_args);
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
|
||||||
|
static function get(string $uri, callable $callback)
|
||||||
|
{self::match('get', $uri, $callback);}
|
||||||
|
static function post(string $uri, callable $callback)
|
||||||
|
{self::match('post', $uri, $callback);}
|
||||||
|
static function put(string $uri, callable $callback)
|
||||||
|
{self::match('put', $uri, $callback);}
|
||||||
|
static function patch(string $uri, callable $callback)
|
||||||
|
{self::match('patch', $uri, $callback);}
|
||||||
|
static function delete(string $uri, callable $callback)
|
||||||
|
{self::match('delete', $uri, $callback);}
|
||||||
|
static function options(string $uri, callable $callback)
|
||||||
|
{self::match('options', $uri, $callback);}
|
||||||
|
static function form(string $uri, callable $callback)
|
||||||
|
{self::match('get|post', $uri, $callback);}
|
||||||
|
static function any(string $uri, callable $callback)
|
||||||
|
{self::match('get|post|put|patch|delete|options', $uri, $callback);}
|
||||||
|
|
||||||
|
static function use(callable $middleware)
|
||||||
|
{
|
||||||
|
array_push(
|
||||||
|
self::$groups[array_key_last(self::$groups)],
|
||||||
|
$middleware
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static function group(string $prefix = '', ?callable $callback = null)
|
||||||
|
{
|
||||||
|
if (!str_starts_with(
|
||||||
|
$_SERVER['REQUEST_URI'],
|
||||||
|
self::$prefix . $prefix
|
||||||
|
)) return;
|
||||||
|
self::$prefix = self::$prefix . $prefix;
|
||||||
|
array_push(self::$groups, []);
|
||||||
|
$callback();
|
||||||
|
array_pop(self::$groups);
|
||||||
|
self::$prefix = rtrim(self::$prefix, $prefix);
|
||||||
|
}
|
||||||
|
}
|
21
composer.json
Normal file
21
composer.json
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"name": "willysoft/route",
|
||||||
|
"description": "Minimal PHP Router",
|
||||||
|
"type": "library",
|
||||||
|
"require": {
|
||||||
|
"php": ">=8.1.0"
|
||||||
|
},
|
||||||
|
"license": "MIT",
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "noreply",
|
||||||
|
"email": "noreply@willy.club"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"minimum-stability": "dev",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"WillySoft\\": "./"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
64
example.php
Normal file
64
example.php
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use WillySoft\Route as App;
|
||||||
|
|
||||||
|
require __DIR__ . '/../vendor/autoload.php';
|
||||||
|
|
||||||
|
// middlewares provide a convenient mechanism for inspecting and
|
||||||
|
// filtering requests. you can imagine them as a series of "layers"
|
||||||
|
// that requests must pass through before they hit your application.
|
||||||
|
// a layer can be used for auth, rate limiting or anything really
|
||||||
|
App::use(
|
||||||
|
fn() => print('<p>Hello all routes!</p>'));
|
||||||
|
|
||||||
|
// there are shorthands for methods you would expect such as
|
||||||
|
// get|post|put|patch|delete|options
|
||||||
|
App::get('/',
|
||||||
|
fn() => print('homepage'));
|
||||||
|
|
||||||
|
// form is a shorthand that accepts GET and POST methods
|
||||||
|
App::form('/submit',
|
||||||
|
fn() => print('i match on GET and POST methods'));
|
||||||
|
|
||||||
|
// any is a shorthand that does what you would expect
|
||||||
|
App::any('/example',
|
||||||
|
fn() => print('i match on any method'));
|
||||||
|
|
||||||
|
// if not satisfied you can use the match function which takes a
|
||||||
|
// string of methods separated by the pipe symbol
|
||||||
|
App::match('get|post|put', '/match',
|
||||||
|
fn() => print('i match on any method you like'));
|
||||||
|
|
||||||
|
// optional route parameters
|
||||||
|
App::get('/echo/$text?',
|
||||||
|
fn($text = 'You sent nothing') => print($text));
|
||||||
|
|
||||||
|
// required route parameters
|
||||||
|
App::get('/echo_must_supply_text/$text',
|
||||||
|
fn($text) => print($text));
|
||||||
|
|
||||||
|
// group together routes and middlewares. a prefix can be added to
|
||||||
|
// prefix each route in the group with a given URI. the group will
|
||||||
|
// be skipped if the request URI does not begin with the one supplied.
|
||||||
|
// middlewares defined in here will only affect routes matched from
|
||||||
|
// within or any child groups
|
||||||
|
App::group('/test', function() {
|
||||||
|
App::use(
|
||||||
|
fn() => print('<p>Hello all routes matched within this or any child groups!</p>'));
|
||||||
|
|
||||||
|
// this will be matched as /test/
|
||||||
|
App::get('/',
|
||||||
|
fn() => print('Testing 123'));
|
||||||
|
|
||||||
|
// you may also define a group without a prefix
|
||||||
|
App::group(callback: function() {
|
||||||
|
App::get('/test',
|
||||||
|
fn() => print('Testing 456'));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// finally, since no route was matched, show a 404 page
|
||||||
|
http_response_code(404);
|
||||||
|
?>
|
||||||
|
<h1>404 not found</h1>
|
||||||
|
<p>Sorry, the page you requested could not be found</p>
|
Loading…
Reference in New Issue
Block a user