Slim是一个提供路由功能的小型PHP框架,这个框架提供了一个强大并且有特色的中间件的概念。Slim实现了Rack协议,在很多Rudy框架中实现的通用管道框架。然后中间件可以用来包装程序,并且能够访问并影响程序的环境。
对于各种不同的需要筛选服务的Slim项目来说中间件是一个很有说服力的解决方案。我会解释中间件是怎样工作,并分享一个简单的缓存实例,说明一下你可以怎么实现自定义的中间件。
理解中间件
Slim文档比喻Slim框架就像一个洋葱,洋葱的每一层都是一个中间件。更好的理解是,让我们假设我们正在编写一个有验证机制和缓存的程序。我们的架构可能看起来像以下的结构:

该代码是负责生成被几层中间件包裹的页面内容,最重要的是验证逻辑和缓存逻辑。
执行的流程是经过每一层,并判断是允许到下一个或是跳出。首先进行检查以验证用户身份。如果不是,流程中断并反馈HTTP 401状态。然后检查看看缓存的拷贝是否可用。如果是,流程中断并返回的页面的缓存开呗。其他层的中间件可能直到最终负责生成页面的流程到达时才会生成在。
当我们的中间件方法返回,执行流程的气泡回到了他们。剩下的逻辑缓存中间件,例如,将为缓存页面内容以备后用。
中间件的实现
看如何去实现自定义中间件,让我们看看代码,可以参考上面的缓存中间件。
实施任何基本的Slim中间件组件的要求实际上是相当小的。我们只需要写一个类,并重写call()并 slimmiddleware延伸方法。中间件的切入点是这个call()方法,我们可以回到从(从而中断执行流)或调用下一层。
<?php
namespace MyMiddleware;
class Cache extends SlimMiddleware
{
protected $db;
public function __construct(PDO $db)
{
$this->db = $db;
}
public function call()
{
$key = $this->app->request()->getResourceUri();
$rsp = $this->app->response();
$data = $this->fetch($key);
if ($data) {
// cache hit... return the cached content
$rsp["Content-Type"] = $data["content_type"];
$rsp->body($data["body"]);
return;
}
// cache miss... continue on to generate the page
$this->next->call();
if ($rsp->status() == 200) {
// cache result for future look up
$this->save($key, $rsp["Content-Type"], $rsp->body());
}
}
protected function fetch($key)
{
$query = "SELECT content_type, body FROM cache
WHERE key = " . $this->db->quote($key);
$result = $this->db->query($query);
$row = $result->fetch(PDO::FETCH_ASSOC);
$result->closeCursor();
return $row;
}
protected function save($key, $contentType, $body)
{
$query = sprintf("INSERT INTO cache (key, content_type, body)
VALUES (%s, %s, %s)",
$this->db->quote($key),
$this->db->quote($contentType),
$this->db->quote($body)
);
$this->db->query($query);
}
}
该方法首先检查call()内容是否在缓存中可用。如果是,它设置响应的内容类型的头和身体,然后返回。如果有一个高速缓存未命中,那么$this->next->call()被执行调用下一层中间件。当流程从其他中间件调用返回该点时,会进行快速检查当前请求的状态和并缓存相关的数据以备将来使用。
因为类扩展了Slim的中间件类,它可以通过$this->app来使用类的实例,从而间接访问响应和请求的对象。我们可以改变相应的头部,从而可以像数组一样使用返回数据,并且返回的数据使用了body()方法。
fetch()和 save()方法是受保护的帮助方法,进行数据库的查询,并保持数据的一致性。它假定表的结构是key,content_type和body。你的持久化机制可能不同,这取决于您的需要。同时,这里没有实现(为简单起见)缓存过期机制,可以在自己的项目中进行实现。
注册并配置中间件
注册中间件在Slim的add方法中实现。
<?php
require_once "../vendor/autoload.php";
$app = new SlimSlim();
$app->add(new MyMiddlewareCache($db));
当然,通过随后调用的add方法可以注册一个以上的中间件可以注册。因为新的中间件围绕任何以前添加的中间件,这意味着他们必须根据他们的调用的顺序反向添加。
<?php
$app = new SlimSlim();
$app->add(new MyMiddlewareCache($db));
$app->add(new MyMiddlewareAuth($db));
// ...
在上面的例子中,缓存中间件包装Slim的应用程序,然后验证中间件包的缓存。当$app->run()被调用,执行的流程将类似于上图,首先进入认证中间件,并根据路由的方式执行。
配置中间件一般是通过服务的构造函数完成。在我们的例子中,我只是简单的建立了一活动数据库连接并访问缓存表,但是你可以根据自己的需求进行自定义。例如,组件可以被重新,并使用fetch()和save()方法处理对象;这将允许我们去掉实例方法,并根据他们的要求提供的组件的配置。
原文链接