kaawikaconnell / fruiter

一个简单的路由库。高度受函数式编程的启发。

dev-master 2020-02-13 00:04 UTC

This package is auto-updated.

Last update: 2024-09-13 09:36:04 UTC


README

一个简单的路由库。高度受函数式编程的启发。跳转到 安装

这个项目是为了挑战我自己而创建的。我在之前玩过Laravel,并使用了他们的路由器,但从未真正有信心理解它在做什么。我怀疑编写这个库将不会让我完全理解Laravel在做什么(因为我编写它之前没有麻烦地去查看它的源代码),但我喜欢从头开始编写一个路由库,尝试自己解决遇到的所有问题。我还用这个项目来探索函数式编程。起初一切都是高阶函数(一个要么接受一个函数作为参数要么返回一个函数的函数),但最终我转向了类。我仍然遵循了一些函数式原则来构建这个项目。除此之外,安装和使用说明如下。

安装

您可以通过Composer安装此包,或者下载它并将 fruiter.php 包含在您的程序中。

通过Composer安装

在您的项目根目录中运行以下命令

composer require kawikaconnell/fruiter

手动安装

  1. 点击右上角的绿色 克隆或下载
  2. 选择一个选项(通过https或ssh克隆,在桌面打开,或下载zip文件)
  3. 确保代码在项目根目录中某个地方
  4. 需要它 require_once '/where/ever/you/put/it/fruiter.php';

用法

以下是一个基本的用法示例

<?php

declare(strict_types=1);

require_once '/where/ever/you/put/it/fruiter.php'; 

use KawikaConnell\Fruiter\Route;
use function KawikaConnell\Fruiter\uri_router;
use function KawikaConnell\Fruiter\get_path_from_url;

$index = new Route('/', function() {
  return 'Hello World!';
});
$greeter = new Route('/hello/{name}', function(array $arguments) {
  return "Hello {$arguments['name']}";
});
$routes = [$index, $greeter];

$path   = get_path_from_url($url);
$result = uri_router($routes, $path);
if ($result === null) {
    http_response_code(404);
    echo "404 ERROR";
    die();
}

$action    = $result->getRoute()->getAction();
$arguments = $result->getArguments();

echo $action($arguments);

RoutingResult

KawikaConnell\Fruiter\RoutingResult 是一个类,用于保存

  • 匹配查询的路由,
  • 以及从查询中提取的参数。您可以通过 getRoute()getArguments() 方法访问这些信息
$routingResult = new KawikaConnell\Fruiter\RoutingResult(new Route(...), []);
$routingResult->getRoute();     // Route
$routingResult->getArguments(); // array

这是Fruiter中所有路由器返回的内容。如果您正在编写会修改 RoutingResult 中数据的代码,您将不得不创建一个新的实例,因为它是不可变的。假设您想将 RoutingResult 中的每个参数都追加 '-ish',

$routingResult = new KawikaConnell\Fruiter\RoutingResult(
  new Route('/{person}/{company}', ...),
  ['person' => 'John', 'company' => 'John Co']
);

function ishizeArguments($routingResult) {
  $arguments = $routingResult->getArguments();
  
  foreach ($arguments as $argumentName => $argument) {
    $arguments[$argumentName] = $argument.'-ish';
  }

  return new KawikaConnell\Fruiter\RoutingResult($routingResult->getRoute(), $arguments);
}

$routingResult = ishizeArguments($routingResult);
$routingResult->getArguments(); // ['person' => 'John-ish', 'company' => 'John Co-ish']

Route

KawikaConnell\Fruiter\Route 是一个类,用于保存一个模式和一个操作。您可以通过 getPattern()getAction 方法访问这些信息。

$route = new KawikaConnell\Fruiter\Route('/', function(...) {...});

$route->getPattern(); // "/" (string) 
$route->getAction();  // Closure

此类不会强制查询匹配模式,您需要在调用操作之前确保查询是否匹配模式。Fruiter中的所有路由器都会为您执行此操作,因为它们返回匹配查询的路由。

Matcher

KawikaConnell\Fruiter\Matcher 是Fruiter的核心组件。它用于确定查询是否匹配模式,并从查询中提取参数,正如模式中定义的那样。匹配器将模式和查询分割成块,并比较查询中的块与模式中的对应块以确定它们是否匹配。

示例

以下所有示例中,假设所有匹配的分隔符都是 '/'。

无参数的模式

无参数的模式需要完全匹配。

以下示例产生匹配

pattern = '/about'
query   = '/about'
-----------------------
matches = true
argumentsExtracted = []

以下示例不产生匹配

pattern = '/about'
query   = '/products'
-----------------------
matches = false
argumentsExtracted = []
必需参数

默认情况下,参数是必需的。它们定义如下 {this},其中 'this' 是参数名称。如果从查询中提取了一个参数,则其键将作为模式中定义的参数名称。

pattern = '/page/{page}'
query   = '/page/about-us'
-----------------------
matches = true
argumentsExtracted = [
  'page' = 'about-us'
]

带有参数的模式比没有参数的模式要宽松,因为唯一的要求是提供值。

可选参数

可选参数是可选的,因此如果查询缺少一个片段,并且该片段是可选的,则查询仍然与模式匹配。

pattern = '/project/{projectId}/{?taskId}'
query   = '/project/123'
-----------------------
matches = true
argumentsExtracted = [
  projectId = 123
  taskId    = null
]

可以连续有多个可选参数。

pattern = '/project/{?projectId}/{?taskId}'
query   = '/project'
-----------------------
matches = true
argumentsExtracted = [
  projectId = null
  taskId    = null
]

如果未提供可选参数的值,则匹配器将分配 null 作为参数值。因此,可选参数总是被填充。在可选参数后面跟有必需参数时,需要将该可选参数分配一个值,因为它从左到右评估查询,检查该顺序中的每个参数。这使得在可选参数之后如果有必需参数,则可选参数变为必需。

pattern = '/checkedFirst/{?checkedSecond}/{checkedThird}'
query   = '/checkedFirst/this'
-----------------------
matches = false // because checkedThird doesn't have a corresponding chunk in the query.
argumentsExtracted = []

想法

  • 创建一个同时检查匹配方法和处理HTTP错误的HTTP路由器。
  • 创建一个命令行应用程序路由器,该路由器考虑了短标志、长标志和标志参数的标志。