ginger-tek/routy

一个简单、健壮的PHP路由器,用于快速开发应用程序和API

3.6.2 2024-09-09 00:15 UTC

This package is auto-updated.

Last update: 2024-09-09 00:26:47 UTC


README

Routy

一个简单、健壮的PHP路由器,用于快速开发应用程序和API

入门

Composer

composer require ginger-tek/routy
require 'vendor/autoload.php';

use GingerTek\Routy;

$app = new Routy();

启动示例

每个路由的处理程序可以是任何可调用的类型,例如普通函数、箭头函数、闭包变量或静态类方法。

$app = new Routy();

// Standard Function
$app->get('/things', function (Routy $app) {
  $app->sendData('Hello!');
});

// Arrow Function
$app->get('/', fn (Routy $app) => $app->sendData('Hello!'););

// Closure
$handler = function (Routy $app) {
  $app->sendData('Hello!');
};

$app->get('/closure', $handler);

// Static Class Method
class ProductsController {
  static function getAll($app) {
    $app->sendData('Hello!');
  }
}

$app->get('/products', \ProductsController::getAll(...));

配置

可以将可选配置的关联数组传递给构造函数。

  • base 用于设置运行时子目录的全局基本URI
  • layout 用于设置用于 render() 响应方法的默认布局模板文件
$app = new Routy([
  'base' => '/api',
  'layout' => 'path/to/layout.php'
])

特性

方法包装器

使用方法包装器进行路由GET、POST、PUT、PATCH或DELETE方法请求。还有一个匹配所有标准HTTP方法(包括HEAD和OPTIONS)的通配符包装器。

$app->get('/products', ...); // HTTP GET
$app->post('/products/:id', ...); // HTTP POST
$app->put('/products', ...); // HTTP PUT
$app->patch('/products/:id', ...); // HTTP PATCH
$app->delete('/products/:id', ...); // HTTP DELETE
$app->any('/products/:id', ...); // HTTP GET, POST, PUT, PATCH, DELETE, HEAD, and OPTIONS

使用 * 作为路由参数匹配任何路由。

$app->get('*', ...); // HTTP GET for all routes
$app->any('*', ...); // Any standard HTTP method for all routes

自定义路由

您还可以直接使用 route() 方法,这是常用包装器下面的方法,以创建更具体的匹配路由条件。

$app->route('GET|POST', '/form', ...); // HTTP GET and POST for the /form route
$app->route('GET|POST|PUT', '/products', ...); // HTTP GET, POST and PUT for the /products route

动态路由

要定义动态路由参数,请使用 :param 语法,并通过 $app 上下文上的 params 对象访问它们。

$app->get('/products/:id', function(Routy $app) {
  $id = $app->params->id;
  // ...
});

中间件

URI字符串参数设置之后的所有参数都被视为中间件函数,包括路由处理程序,因此可以定义所需数量。

使用本地 $_REQUEST$_SESSION 全局变量在中间件/处理程序之间共享数据。

function authenticate(Routy $app) {
  if(!($token = @$app->getHeaders()['authorization']))
    $app->end(401);
  $_REQUEST['user'] = parseToken($token);
}

$app->get('/products', authenticate(...), function (Routy $app) {
  $userId = $_REQUEST['user']->id;
  $items = getProductsByUser($userId);
  $app->sendJson($items);
});

路由分组

您可以使用 group() 方法定义路由分组。

$app = new Routy();

$app->group('/products', function (Routy $app) {
  $app->post('/', ...);
  $app->get('/', ...);
  $app->get('/:id', ...);
  $app->patch('/:id', ...);
});

您还可以向嵌套路由添加中间件

$app->group('/products', authenticate(...), function (Routy $app) {
  $app->get('/', ...);
});

后备路由

后备路由用于返回自定义的404响应,或在其他返回之前执行其他逻辑。

要设置后备路由,请使用 notFound() 方法设置一个处理函数,该函数将具有已设置HTTP 404响应头的响应。

后备路由的作用域是它们定义的地方,并且只有在它们匹配传入URI的父路径时才会被访问。

$app = new Routy();                        

$app->group('/products', function (Routy $app) {
  $app->get('/', fn (Routy $app) => $app->sendJson([]));

  // GET /products/asdf will end up here
  $app->notFound(function (Routy $app) { ... });
});

// GET /asdf will end up here
$app->notFound(function (Routy $app) { ... });

服务静态文件(SPA)

要从与SPA前端相同的应用程序直接从基本URI服务静态文件,请在所有其他路由定义之后使用 serveStatic() 方法 之后

此功能通常由您的实际Web服务器(Apache/nginx/caddy)执行,因此在生产场景中使用时请谨慎。由于此功能使您的应用程序能够处理文件服务,您的应用程序必须作为文件服务的路由器运行,即 php -S localhost:8000 router.php

$app = new Routy();

$app->group('/api', ApiController::index(...));
$app->serveStatic('public');

如果请求的文件未找到,将提供路径 + index.html。如果没有 index.html 文件,将返回失败路径。


## Request Properties
You can access the incoming HTTP method and URI via the `uri`, `method`, and `params`, and `query` properties on the `$app` instance.
```php
$app->get('/', function (Routy $app) {
  $app->uri;
  $app->method;
  $app->params;
  $app->query;
});

请求辅助方法

有一些辅助方法用于处理传入的请求数据。

getBody()

用于检索传入的有效负载数据。JSON数据将自动解码,表单URL编码数据将作为标准对象访问。

$app->get('/products', function (Routy $app) {
  $body = $app->getBody();

  // JSON
  // { "someProperty": "asdf" }
  $body->someProperty;
  $body->username; // From: <input name="username">
});

getHeaders()

用于检索传入的HTTP头,以关联数组的形式,每个头键都是自动小写化的,以便标准化。

$app->get('/products', function (Routy $app) {
  $headers = $app->getHeaders();
  $headers->authorization; // Bearer eyhdgs9d8fg9s7d87f...
});

getFiles()

用于从multipart/form-data请求检索上传的文件。对于多文件上传返回对象数组。要为单文件上传返回第一个对象,请将第二个参数设置为 true

<form method="POST" action="/upload" enctype="multipart/form-data">
  <input type="file" name="multi[]" multiple required>
  <input type="file" name="single" required>
  <button type="submit">Submit</button>
</form>
$app->post('/upload', function (Routy $app) {
  $multipleFiles = $app->getFiles('multi'); // object array
  $singleFile = $app->getFiles('single', true); // object
});

响应辅助方法

处理响应有很多辅助方法。

sendJson()

用于返回JSON字符串数据

$app->sendJson(['prop' => 'value']); // { "prop": "value" }
$app->sendJson([1, 2, ['three' => 4], 5]); // [1, 2, { "three: 4 }, 5]

sendData()

用于返回字符串数据或文件的原始内容

$app->sendData('<h1>Raw HTML</h1>');
$app->sendData('path/to/file.html');

redirect()

用于发送临时或永久重定向到新的URL

$app->redirect('/go/here'); // HTTP 302
$app->redirect('/new/permanent/location', true); // HTTP 301

render()

用于渲染PHP视图文件,使用标准的PHP包含和变量作用域提取进行MCV建模

您可以通过构造函数配置来设置默认布局

$app = new Routy(['layout' => 'path/to/layout.php']);
...
$app->render('views/home.php');
$app->render('views/about.php')

您还可以通过将layout选项设置为另一个路径来覆盖默认布局

$app = new Routy(['layout' => 'path/to/layout1.php']);
...
$app->render('path/to/view.php', ['layout' => 'path/to/layout2.php']);

或者,您可以通过将layout选项设置为false来不使用布局

$app = new Routy(['layout' => 'path/to/layout.php']);
...
$app->render('path/to/view.php', ['layout' => false]);

您也可以完全不指定布局,直接渲染文件

$app = new Routy();
...
$app->render('path/to/view.php');

最后,将model选项设置为传递数据模型,以便在视图文件中将数据暴露给模板上下文

$app->render('path/to/view.php', [
  'model' => [
    'someProperty' => 'some data'
  ]
]);

// view.php
<div><?= $model->someProperty ?></div>

status()

用于设置HTTP状态码。这可以用于方法链到其他响应方法

$app->post('/products', function (Routy $app) {
  $app->status(400)->sendJson(['error' => 'Bad payload']);
  // or
  $app->status(201)->sendData('Successfully created!');
});

end()

用于立即返回,并可选地设置HTTP状态码

$app->end(); // Success
$app->end(401); // Unauthorized
$app->end(404); // Not Found