pixelkarma/pkrouter

一个可扩展的PHP路由器。

1.0.2 2024-08-25 19:17 UTC

This package is auto-updated.

Last update: 2024-09-04 17:23:47 UTC


README

PkRouter 是一个快速且健壮的现代PHP路由器,旨在用于API创建。它没有依赖项,并鼓励使用面向对象的方法。

请参阅示例以查看其实际应用。

特性

  • 支持所有HTTP方法,包括自定义方法。
  • 灵活的中间件,用于路由前后的执行。
  • 可扩展的请求和响应类,用于处理自定义负载。
  • 支持函数和类方法回调,非常适合MVC项目。
  • 高效的基于正则表达式的路由。
  • 可扩展的参数模式验证。
  • 动态属性可以在请求生命周期的各个阶段无缝地存储数据。
  • 自定义异常增强了错误处理和清晰度。

安装

composer require pixelkarma/pkrouter

用法

use Pixelkarma\PkRouter\PkRouter;

$pkRouter = new PkRouter();

函数

use Pixelkarma\PkRouter\PkRoute;

$pkRouter->routes->addRoute(
  new PkRoute(
    "home", ["GET"], "/",
    function (PkRouter $router) {
      $message = "Hello World!";
      return $router->respond(["message" => $message]);
    }
  )
);
$pkRouter->run();

控制器方法

控制器方法回调

# ./public/index.php
$pkRouter->routes->addRoute(
  new PkRoute("home", ["GET"], "/", "YourNamespace\Controllers\HelloController@sayHello")
);
$pkRouter->run();

路由器 (PkRouter)

  $pkRouter = new PkRouter(
    $routes = null, // An instance of PkRoutesConfig
    $request = null, // An instance of PkRequest
    $response = null, // An instance of PkResponse
    $logFunction = null // a callable function that excepts one Exception parameter
  );

在创建路由器时如果没有传递任何选项,将使用默认类并创建一个空的路由配置。然后您需要单独添加路由。

use Pixelkarma\PkRouter\PkRoute;

$homeRoute = new PkRoute(
  name: "home",
  path: "/",
  methods: ["GET"],
  callback: /* function or class method string */,
  meta: [],
  before: [
    /* PkMiddlewareInterface */
  ],
  after: [
    /* PkMiddlewareInterface */
  ],
);

$pkRouter->routes->addRoute($homeRoute);

查找匹配项

有两种方式可以查找匹配项并执行其回调。

$boolResult = $pkRouter->run();

或者

if (true === $pkRouter->match()) {
  $boolResult = $pkRouter->run();
}else{
  // Handle the 404
}

响应

这是一个到 $router->response->sendJson();快捷方式

$router->respond(["key"=>"value"], 200);

动态属性

在 PkRouter 中,您可以在 $router 实例上设置动态属性。这些属性可以用来存储需要在请求生命周期的不同阶段访问或修改的数据,例如在中间件之前、路由回调和中间件之后。

// Setting up a user object
$router->user = (object)[
  "username" => "j.doe"
];

路由创建

new PkRoute(
  name: "name",
  path: "/path/",
  methods: ["GET", "POST"],
  callback: "YourNamespace\Controllers\HelloController@sayHello",
  meta: [
    "permissions" => "admin"
    "anything" => "else"
  ],
  before: [
    // PkMiddlewareInterface, - run before route
    // PkMiddlewareInterface, ...
  ],
  after: [
    // PkMiddlewareInterface, - run after route
    // PkMiddlewareInterface, ...
  ]
);

路由回调

当找到匹配的路由时,将执行回调。这个值可以是函数,也可以是表示您自己的控制器方法的字符串。两者都应接受一个参数,即 PkRouter 的实例。

函数式回调

// Function
callback: functionName(PkRouter $router)

// Anonymous Function
callback: function(PkRouter $router){
  $router->respond(["message" => "Hello!"]);
}

控制器方法回调

// Controller Method
callback: "YourNamespace\Controllers\ExampleController@methodName"

您的控制器需要在构造函数中接受 $router,而不是方法。

namespace YourNamespace\Controllers;
class ExampleController {
  private $router;
  public function __construct(PkRouter $router) {
    $this->router = $router;
  }
  public function methodName(){
    return $this->router->respond(["message" => "Hello!"]);
  }
}

路由元信息

元信息是一组用于在路由级别提供额外数据的值。这些信息可以从 中间件 和回调中访问。

meta: [
  "userAccess" => ["group1", "group2"],
  "something" => "else"
]

中间件之前和之后

中间件

URL参数

路径: /user/[s:username]/

在这个例子中 s 是类型,而 username 是可访问的参数名称。

$router->request->getParam('username')

PkRoute 方法 了解有关 getParam() 的更多信息

添加额外的匹配模式

通过调用静态函数 addMatchPattern,您可以添加额外的参数类型。这可以在匹配路由之前任何时刻使用。

通常将此放在 路由配置 文件中,如下所示

use Pixelkarma\PkRouter\PkRoute;
use Pixelkarma\PkRouter\PkRoutesConfig;

class MyRoutes extends PkRoutesConfig {
  public function routes(): array {
    /**
     *  Match 'Serial Number' 'AA-1234'
     *  /path/AA-1234/ == /path/[sn:serialNumber]/
     */
    PkRoute::addMatchPattern("sn", "(/^[A-Z]{2}-\d{4}$/)");
    /* add routes here */
  }
}

路由方法

允许使用 $key 参数的方法,如果找不到键,将返回 $default(默认:null)。这在验证有效负载时非常有用,因为您可能需要除 null 之外的值。

$router->route->getParam("userId", false);
$router->route->getParam("userId", 0);
// Returns key value or all `meta` with `getMeta('name')`
$router->route->getMeta(string $key = null, $default = null)

// Returns key value or all `params` with `getParam('name')`
$router->route->getParam(string $key = null, $default = null)

// Returns route name string
$router->route->getName()

// Returns the path `/user/[s:username]/`
$router->route->getPath()

// Returns an array of allowed methods `["GET", "POST"]`
$router->route->getMethods()

路由配置

PkRoutesConfig 是一个可扩展的类,用于设置多个路由并添加中间件。

# ./public/index.php
use Pixelkarma\PkRouter\PkRouter;
$pkRouter = new PkRouter(new MyRoutes());
$pkRouter->run();
# ./src/Routes/MyRoutes.php
namespace YourNamespace\Router;

use YourNamespace\Router\Middleware\AuthorizationMiddleware;
use YourNamespace\Router\Middleware\AnalyticsMiddleware;

use Pixelkarma\PkRouter\PkRoute;
use Pixelkarma\PkRouter\PkRoutesConfig;

class MyRoutes extends PkRoutesConfig {
  public function routes(): array {

    // Define Middleware
    $authorizationMiddleware = new AuthorizationMiddleware();
    $analyticsMiddleware = new AnalyticsMiddleware();

    // Create Routes
    $readRoute = new PkRoute(
      name: "read",
      path: "/storage/",
      methods: ["GET"],
      callback: "YourNamespace\Controllers\StorageController@read",
      after: [
        $analyticsMiddleware,
      ]
    );

    $writeRoute = new PkRoute(
      name: "write",
      path: "/storage/",
      methods: ["POST"],
      callback: "YourNamespace\Controllers\StorageController@write",
      before: [
        $authorizationMiddleware,
      ],
      after: [
        $analyticsMiddleware,
      ]
    );

    // Return all routes
    return [$readRoute, $writeRoute];
  }
}

请求 (PkRequest)

PkRequest 包含正在进行的请求的所有信息。

请求方法

允许使用 $key 参数的方法,如果没有数据,将返回 $default(默认:null)。这在验证有效负载时非常有用,因为您可能需要除 null 之外的值。

$router->request->getHeader("authorization", false);
$router->request->getHeader("user-agent", "Unknown");
// Returns key value or all `headers` with `getHeader('name')`
$router->request->getHeader(string $key = null, $default = null);

// Returns key value or all `?query=string` with `getQuery('name')`
$router->request->getQuery(string $key = null, $default = null);

// Returns key value or all `body content` with `getBody('name')`
$router->request->getBody(string $key = null, $default = null);

// Returns key value or all `cookies` with `getCookie('name')`
$router->request->getCookie(string $key = null, $default = null);

// Returns key value or all `$_FILES` with `getFile('name')`
$router->request->getFile(string $key = null, $default = null);

// Returns a string like "GET" or "POST"
$router->request->getMethod();

// Returns true if the connection is SSL
$router->request->isSecure();

// Returns the hostname
$router->request->getHost();

// Returns the requested path
$router->request->getPath();

// Returns the Content-Type, usually `application/json`
$router->request->getContentType();

// Returns the RAW body of the request.
$router->request->getRawBody();

// Returns "https" or "http"
$router->request->getScheme();

// Returns the port: 80, 443
$router->request->getPort();

// Returns the `username` in http://username:password@hostname/path
// !DANGER! This is insecure and depreciated. Use with caution.
$router->request->getUser();

// Returns the `password` in http://username:password@hostname/path
// !DANGER! This is insecure and depreciated. Use with caution.
$router->request->getPass();

响应 (PkResponse)

直到 有效负载 发送,才发送头部和响应代码。

// Add a response header.
$router->response->setHeader(string $name, string $value = '');

// Clear all set response headers
$router->response->clearHeaders();

// Set the response code (200, 404, 500, ...)
$router->response->setCode(int $code);

// Sends an Array as JSON.
// Optionally set the http response code.
$router->response->sendJson(array $payload, int $code = null);
/* also */ $router->respond(array $payload, int $code = null);

// Sends whatever you pass without processing it.
// Optionally set the http response code.
$router->response->sendRaw($payload, int $code = null);

// Returns the response payload exactly how it was sent.
$router->response->getPayload();

扩展 PkResponse

PkRouter 默认只支持 JSON,但您可以扩展它以实现更多功能。

# ./src/Router/CustomResponse.php
namespace YourNamespace\Router;

use Pixelkarma\PkRouter\PkResponse;

class CustomResponse extends PkResponse {
  public function sendXml($xml, int $code = null): bool {
    $this->setHeader('Content-Type', 'application/xml');
    return $this->sendRaw($xml, $code);
  }
}
# ./public/index.php
use YourNamespace\Router\CustomResponse;

// Create PkRouter with your response class
$pkRouter = new PkRouter(
  response: new CustomResponse()
);
# ./src/Controllers/MyController.php
namespace YourNamespace\Controllers;

use Pixelkarma\PkRouter\PkRouter;

class MyController {
  private $router;

  public function __construct(PkRouter $router) {
    $this->router = $router;
  }

  public function getXml(){
    // Execute in your controller/function
    $this->router->response->sendXml($xmlData, int $code = null);
  }
}

中间件

中间件是 PkMiddlewareInterface 的实例,可以在您的路由代码之前和有效负载发送后运行。

注意:中间件的执行顺序与您在数组中的放置顺序一致。

new PkRoute(
  /* ... */
  before: [
    /* PkMiddlewareInterface,
       PkMiddlewareInterface */
  ],
  after: [
    /* PkMiddlewareInterface */
  ],
);

创建您自己的中间件

注意:如果您的 handle() 函数返回 false,则不会继续到下一个中间件。路由将结束,run() 将返回 false。如果您需要在中间件之间传递数据,请考虑返回一个数组或对象。

namespace YourNamespace\Router\Middleware;

use Pixelkarma\PkRouter\PkMiddlewareInterface;
use Pixelkarma\PkRouter\PkRouter;

class AuthorizationMiddleware implements PkMiddlewareInterface {
  public function handle(PkRouter $router, $previous = null) {
    // Check the headers for `auth-token`
    if (false === $router->request->getHeader("auth-token", false)) {
      $router->response->sendRaw("Unauthorized", 401);
      exit; // Also acceptable to return false or throw and Exception
    }
    $router->user = YourAuthorizationCode(
                      $router->request->getHeader("auth-token")
                    );
    return true;
  }
}

在中间件之间传递信息

注意:中间件返回值不会传递给回调。请参阅 动态属性

public function handle(PkRouter $router, $previous = 0) {
  $count = $previous + 1;
  print "Count: {$count}\n";
  return $count;
}
Count: 1
Count: 2
Count: 3
Count: 4

许可证

MIT 许可证,请参阅 LICENSE.md

版权所有 (c) 2024 Pixel Karma, LLC social+pkrouter@pixelkarma.com