Slim 应用的路由和中间件都是通过PSR 7响应对象去返回当前HTTP响应给客户端.这个对象是 PSR 7 ResponseInterface 的实现.我们可以通过它去操作和HTTP响应的状态,头部和正文.
怎样获取响应对象
PSR 7响应对象已经作为Slim应用路由的回调函数的第二个参数被注入了,你可以直接使用:
示例:
<?php
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;
$app = new \Slim\App;
$app->get('/foo', function (ServerRequestInterface $request, ResponseInterface $response) {
// Use the PSR 7 $response object
return $response;
});
$app->run();
在Slim中间件中也是如此,第二个参数就是PSR 7响应对象:
示例:
<?php
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;
$app = new \Slim\App;
$app->add(function (ServerRequestInterface $request, ResponseInterface $response, callable $next) {
// Use the PSR 7 $response object
return $next($request, $response);
});
// Define app routes...
$app->run();
响应状态
任何一个HTTP响应都有一个数字的状态码(status code).响应状态表示返回给客户端的响应的类型.PSR 7响应对象默认的响应状态码是 200(ok).你可以通过PSR 7响应对象的方法 getStatusCode()
获取响应状态码.
$status = $response->getStatusCode();
我们也可以复制一个PSR 7响应对象,并重新给状态码一个值:
$newResponse = $response->withStatus(302);
响应头部
任何一个HTTP响应都有响应头部,响应头部作为元数据描述了HTTP响应,但是他们在响应正文里面是看不到的,Slim PSR 7提供了一些方法去操作和检查响应头部.
获取所有的头部信息
你可以通过 PSR 7响应对象的方法 getHeaders()
获取所有的头部信息,结果以索引数组形式返回.返回的索引数组键名为header名称,数组值是一个数字索引数组,header名称所表示的值
示例:
$headers = $response->getHeaders();
foreach ($headers as $name => $values) {
echo $name . ": " . implode(", ", $values);
}
获取某一个header信息
你也可以只获取header中的一条信息,通过PSR 7响应对象的 getHeader($name)
方法.返回一个数组,数组值是$name所表示的值.但是切记,一个头部名有可能有很多条值:
示例:
$headerValueArray = $response->getHeader('Vary');
当然你也可以通过另一个PSR 7的响应对象方法 getHeaderLine($name)
获取一条信息,返回的是一个以逗号分隔的字符串:
示例:
$headerValueString = $response->getHeaderLine('Vary');
检查头部
你可以通过PSR 7响应对象的方法hasHeader($name)
判断某一条响应头是否存在
if ($response->hasHeader('Vary')) {
// Do something
}
设置头部
我们可以通过PSR 7响应对象的方法 withHeader($name, $value)
设置一个响应头
$newResponse = $oldResponse->withHeader('Content-type', 'application/json');
注意:
响应对象是不可改变的.这个方法是复制一个响应对象并改变它的值,这个方式是破坏性的,它会替换掉之前已经存在的同名称的值
使用示例:由于响应对象值时不可改变的并不会有X-By http header存在
$app->get('/',function ($request, $response) {
$response->withHeader('X-By',1234);
return $response->write('hello');
});
如果确实要添加http头部,应该如此
$app->get('/',function ($request, $response) {
$newresponse = $response->withHeader('X-By',1211);
return $newresponse->write('hello');
});
那为什么说它是破坏性的呢
$app->get('/',function ($request, $response) {
$newresponse = $response->withHeader('X-By',1234);
$new_response = $newresponse->withHeader('X-By',1034);
return $new_response->write('hello');
});
这样在响应中X-By的值为1034,会把之前的值替换掉
添加头部
你可以通过psr 7响应对象的方法 withAddedHeader($name, $value)
添加一条header
$newResponse = $oldResponse->withAddedHeader('Allow', 'PUT');
注意:
不同于withHeader方法,这个方法会增加一个新值,如果你设置的header 名称已经存在的话,因为psr 7对象时不可改变的,因此在赋值的对象中会会存在新的值与旧的值。
示例:
$app->get('/',function ($request, $response) {
$newresponse = $response->withHeader('X-By',1234);
$new_response = $newresponse->withAddedHeader('X-By',1034);
return $new_response->write('hello');
});
http Header中 X-By有两条记录值分别为 1234和1034
移除Header
你可以通过PSR 7响应对象的方法 withoutHeader($name)移除某些header值
$newResponse = $oldResponse->withoutHeader('Allow');
注意:
因为PSR 7对象是不可改变的,因此也必须复制一个新的PSR 7对象。
响应正文
一个HTTP响应一般都有响应正文,Slim 提供一个PSR7响应对象去检查和操作最终的响应正文。
如果PSR7请求对象一样,PSR7响应对象操作响应正文是通过以操作接口 \Psr\Http\Message\StreamInterface
的实现的方式,你可以通过PSR7响应对象的getBody()方法获得响应正文 StreamInterface 的实例,getBody()方法更适合于输出未知长度或者不知大小的情况。
$body = $response->getBody();
\Psr\Http\Message\StreamInterface
提供了下面的方法去读取,迭代和在PHP资源下进行修改
* getSize()
* tell()
* eof()
* isSeekable()
* seek()
* rewind()
* isWritable()
* write($string)
* isReadable()
* read($length)
* getContents()
* getMetadata($key = null)
大多数情况下,你可能需要往PSR7响应对象的写入东西,你可以通过 StreamInterface 实例的方法write()实现
$body = $response->getBody();
$body->write('Hello');
你可以使用一个新的 StreamInterface 替换现在PSR7响应对象的body,这是非常有用的当你想获取内容通过远程的目的地的(例如:文件系统或者远程api)并写入响应的时候,你可以替换PSR7响应对象的body通过withBody(StreamInterface $body) 方法,但是它的参数必须是\Psr\Http\Message\StreamInterface
的实现
$newStream = new \GuzzleHttp\Psr7\LazyOpenStream('/path/to/file', 'r');
$newResponse = $oldResponse->withBody($newStream);
注意:
PSR7响应对象是不可改变的,必须复制一个新的对象
文档翻译的并不是很专业,仅供个人学习作用,建议看官方文档。
如有兴趣,请看下一篇 SLIM 3 文档(九)-路由2)