我正在寻求有关如何合并响应类以返回 HTTP 响应代码的帮助。我是一名 PHP 新手,并使用它来提高我的编码技能和对框架的理解。我应该将响应类放在
$app->run()
中还是放在 Kernel.php 文件中 $this-router-dispatch()
中?
默认响应代码应该是 200,除非我指定不同的值,例如 404、405、500 等...
我在文件中添加了注释以显示应返回哪些状态代码。
这是我的文件:
index.php
$app = new Kernel();
require_once dirname(__DIR__).'/routes/web.php';
$app->run();
内核.php
class Kernel
{
public static Kernel $app;
public Request $request;
public Response $response;
public Router $router;
public function __construct()
{
self::$app = $this;
$this->request = new Request();
$this->response = new Response();
$this->router = new Router();
}
public function run(): void
{
$this->router->dispatch($this->request->path(), $this->request->method());
}
}
请求.php
class Request
{
public function method(): string
{
if (!in_array($method = strtoupper($_SERVER['REQUEST_METHOD']), ['GET', 'POST'], true))
{
// This should return a 405 response code.
}
return $method;
}
public function path(): false|int|array|string|null
{
return parse_url($_SERVER['REQUEST_URI'],PHP_URL_PATH);
}
}
路由器.php
class Router
{
protected array $routes = [];
public function dispatch($path, $method): void
{
// route found
// return controller and status 200
// route not found
// return 405 status code
}
}
响应.php
class Response
{
public const HTTP_OK = 200;
public const HTTP_NOT_FOUND = 404;
public const HTTP_METHOD_NOT_ALLOWED = 405;
// Not sure what to do here.
public function setStatusCode()
{
}
}
Response 类的主要用途是在控制器中以及调度路由器之后。 首先,您需要一个名为 make 的静态方法来为您创建一个对象(工厂模式)。
// Response
public static function make(): static
{
return new static();
}
在你的控制器中,你可以使用这样的东西:
// A Controller
return Response::make()->setBody($pc->toArray())->setStatusCode(201);
在上面的示例中,您会看到一个名为
setBody
的额外方法,因此每个响应都有一个正文。
响应类必须表示 HTTP 响应,因此您需要添加
body
和 statusCode
作为类属性。
Response 类中的 setter 必须是方法链接,以便通过无序调用它们来帮助用户。
这是 Response 类的完整示例:
<?php
namespace Core;
class Response
{
public const HTTP_OK = 200;
public const HTTP_NOT_FOUND = 404;
public const HTTP_METHOD_NOT_ALLOWED = 405;
private string $body = '';
private int $statusCode = 200;
public static function make(): static
{
return new static();
}
public function setStatusCode(int $statusCode): static
{
$this->statusCode = $statusCode;
return $this;
}
public function getStatusCode(): int
{
return $this->statusCode;
}
public function setBody($body): static
{
if (is_array($body)) {
header('Content-Type: application/json');
$body = json_encode($body);
}
$this->body = $body;
return $this;
}
public function getBody(): string
{
return $this->body;
}
}
在此之后,我们可以完成
run
方法并通过简单地设置响应中的状态代码并回显正文来返回我们的响应:
public function run(): void
{
$response = $this->router->dispatch($this->request->path(), $this->request->method());
http_response_code($response->getStatusCode());
echo $response->getBody();
}
这里有一个重要的注意事项:路由器调度必须返回从控制器接收到的响应。
这是一个路由器类示例,您可以使用它来了解调度应该是什么样子:
<?php
namespace Core;
use DI\DependencyException;
use DI\NotFoundException;
use Exception;
class Router
{
protected static array $routes = [];
public function __construct(protected Request $request, protected Response $response)
{
include_once __DIR__ . '/../routes/api.php';
}
public static function get($path, $callback): void
{
self::$routes['get'][$path] = $callback;
}
public static function post($path, $callback): void
{
self::$routes['post'][$path] = $callback;
}
public static function put($path, $callback): void
{
self::$routes['put'][$path] = $callback;
}
public static function patch($path, $callback): void
{
self::$routes['patch'][$path] = $callback;
}
public static function delete($path, $callback): void
{
self::$routes['delete'][$path] = $callback;
}
/**
* @throws DependencyException
* @throws NotFoundException
* @throws Exception
*/
public function resolve(): Response
{
$path = $this->request->getPath();
$method = $this->request->getMethod();
$callback = self::$routes[$method][$path] ?? false;
if ($callback === false) {
return $this->response->setBody('Not Found')->setStatusCode(404);
}
if (is_array($callback)) {
$fn = Application::$container->get($callback[0]);
array_shift($callback);
$callback = array_merge([$fn], $callback);
}
$response = call_user_func($callback, $this);
if (! $response instanceof Response) {
throw new Exception('You must return a Response object');
}
return $response;
}
}
我在路由器中使用了自动布线来更轻松地创建控制器对象。