让我们从一个超小的应用程序入手,对 Fluff 的概念做一个基本介绍。我们的目标很简单,实现一个在网络上流传已久的“价值过亿的人工智能程序”。
这个应用需要从环境中构建一个 PSR-7 Server Request 作为请求的载体,所以开始之前,我们首先用 nyholm/psr7-server 组件来生成这个 request 对象.
use Nyholm\Psr7\Factory\Psr17Factory;
use Nyholm\Psr7Server\ServerRequestCreator;
use Psr\Http\Message\ServerRequestInterface;
$psr17Factory = new Psr17Factory();
$creator = new ServerRequestCreator(
$psr17Factory,
$psr17Factory,
$psr17Factory,
$psr17Factory
);
/** @var ServerRequestInterface $request */
$request = $creator->fromGlobals();
OK, 准备工作结束,进入正题!我们要实现的是一个对话程序,它可以智能的回答用户的任何提问。首先,我们向 request handler
传入一个 callable 类型的对象作为主要的逻辑处理程序。
# index.php
use ConstanzeStandard\Fluff\Application;
use ConstanzeStandard\Fluff\RequestHandler\Args;
use Psr\Http\Message\ServerRequestInterface;
use Nyholm\Psr7\Response;
$core = new Args(function(ServerRequestInterface $request) {
$queryParams = $request->getQueryParams();
$words = $queryParams['words'];
$words = str_replace(
['吗', '?', '?'],
['', '!', '!'],
$words
);
return new Response(200, ['Content-Type' => 'text/plain'], $words);
});
$app = new Application($core);
$app->handle($request);
request handler
是 Fluff 的核心,它承载了一个请求的主要逻辑(包括请求处理和业务逻辑)Fluff 提供了多种 request handler
,通过将不同的 request handler
进行组合,可以衍生出多种架构模式。以上我们使用了一个基本的、单一的 request handler: Args
.
恭喜你!现在,你已经完成了人工智能部分的全部逻辑,让我们访问 http://127.0.0.1:8080?words=在吗? 看看效果!
“哦?怎么会?只出现了一个空白页面......”
这并不是 bug 哦~ 只是因为我们没有输出 Response
. 是的,这与我们以往使用的框架不同,想要输出 response,我们就需要找到作用于输出缓冲区(Output Buffer)
的中间件 EndOutputBuffer
, 将这个中间件添加到 Application
中。让我们来重构这段代码:
use ConstanzeStandard\Fluff\Middleware\EndOutputBuffer;
...
$app = new Application($core);
$app->addMiddleware(new EndOutputBuffer());
$app->handle($request);
EndOutputBuffer
的职责是关闭缓冲区,并且会冲刷掉带有 flushable
标志的输出缓冲区,或清空带有 cleanable
标志的输出缓冲区,最终将所有缓冲区关闭。
现在,我们再来访问一次 http://127.0.0.1:8080?words=在吗?
在!
上面的例子中有一个不合理的地方,就是如果我们没有传入 words
参数,程序就会崩溃,于是我们决定添加一个验证 GET 请求参数的中间件(Middleware)
。Fluff 的中间件系统符合 PSR-15
的标准,你的中间件也必须实现 \Psr\Http\Server\MiddlewareInterface
接口。
下面,我们来实现这个验证请求的中间件,如果请求没有传递 words
参数,则直接返回 400 Bad Request
响应。
use Nyholm\Psr7\Response;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
class VerificationMiddleware implements MiddlewareInterface
{
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$queryParams = $request->getQueryParams();
if (array_key_exists('words', $queryParams)) {
return $handler->handle($request);
}
return new Response(400);
}
}
这个中间件应该放在 EndOutputBuffer
的里层,因为 VerificationMiddleware
需要通过下一层的 EndOutputBuffer
输出响应。在代码中,应该在 EndOutputBuffer
之前添加。
...
$app = new Application($core);
$app->addMiddleware(new VerificationMiddleware());
$app->addMiddleware(new EndOutputBuffer());
$app->handle($request);
我们再来做一下测试,访问 http://127.0.0.1:8080, 是不是出现了 400 Bad Request 的响应呢 :)
到现在,这个最小化应用已经完成了。对于使用者来说,选择何种 request handler, 将决定后续的开发模式,甚至影响代码的风格。而功能的扩展,则很大程度上取决于中间件(Middleware)
的使用。这些组件的使用和搭配,我们将在接下来的几章逐一介绍。
Fluff 微框架由 Alex 创建并维护 / Github home page
Copyright © 2019 Constanze Standard.