SlimPHP开发指南三:相关概念

教科书般的PHP框架学习指南

注:翻译水平有限,如有错误,欢迎指正

PSR 7

Slim supports PSR-7 interfaces for its Request and Response objects. This makes Slim flexible because it can use any PSR-7 implementation. For example, a Slim application route does not have to return an instance of \Slim\Http\Response. It could, for example, return an instance of \GuzzleHttp\Psr7\CachingStream or any instance returned by the \GuzzleHttp\Psr7\stream_for() function.

Slim为其请求和响应对象支持PSR-7接口。这使得Slim非常灵活,因为它可以使用任何PSR-7实现。例如,Slim应用程序路由不必返回\Slim\Http\Response的实例。例如,它可以返回\GuzzleHttp\Psr7\CachingStream的实例,或者\GuzzleHttp\Psr7\stream_for()函数返回的任何实例。

Slim provides its own PSR-7 implementation so that it works out of the box. However, you are free to replace Slim’s default PSR 7 objects with a third-party implementation. Just override the application container’s request and response services so they return an instance of \Psr\Http\Message\ServerRequestInterface and \Psr\Http\Message\ResponseInterface, respectively.

Slim提供了自己的PSR-7实现,因此可以开箱即用。不过,您可以使用第三方实现替换Slim的默认PSR 7对象。只需覆盖应用程序容器的请求和响应服务,以便它们分别返回\Psr\Http\Message\ServerRequestInterface和\Psr\Http\Message\ResponseInterface的实例。

Value objects

Slim’s Request and Response objects are immutable value objects. They can be “changed” only by requesting a cloned version that has updated property values. Value objects have a nominal overhead because they must be cloned when their properties are updated. This overhead does not affect performance in any meaningful way.

Slim的请求和响应对象是不可变的值对象。它们只能通过请求具有更新属性值的克隆版本来“更改”。值对象具有名义开销,因为必须在更新属性时克隆它们。这种开销不会对性能产生实质性的影响。

You can request a copy of a value object by invoking any of its PSR 7 interface methods (these methods typically have a with prefix). For example, a PSR 7 Response object has a withHeader(name,value) method that returns a cloned value object with the new HTTP header.

您可以通过调用值对象的任何PSR 7接口方法来请求值对象的副本(这些方法通常具有带前缀的方法)。例如,PSR 7响应对象有一个withHeader(name,value)方法,该方法使用新的HTTP头返回克隆的值对象。

<?php
$app = new \Slim\App;
$app->get('/foo', function ($req, $res, $args) {
    return $res->withHeader(
        'Content-Type',
        'application/json'
    );
});
$app->run();
复制代码

The PSR 7 interface provides these methods to transform Request and Response objects:

PSR 7接口提供了这些方法来转换请求和响应对象:

  • withProtocolVersion($version)
  • withHeader($name, $value)
  • withAddedHeader($name, $value)
  • withoutHeader($name)
  • withBody(StreamInterface $body)

The PSR 7 interface provides these methods to transform Request objects:

PSR 7接口提供了以下方法来转换请求对象:

  • withMethod($method)
  • withUri(UriInterface $uri, $preserveHost = false)
  • withCookieParams(array $cookies)
  • withQueryParams(array $query)
  • withUploadedFiles(array $uploadedFiles)
  • withParsedBody($data)
  • withAttribute($name, $value)
  • withoutAttribute($name)

The PSR 7 interface provides these methods to transform Response objects:

PSR 7接口提供了以下方法来转换响应对象:

  • withStatus($code, $reasonPhrase = '')

Refer to the PSR-7 documentation for more information about these methods. 有关这些方法的更多信息,请参阅PSR-7文档。

中间件(Middleware)

You can run code before and after your Slim application to manipulate the Request and Response objects as you see fit. This is called middleware. Why would you want to do this? Perhaps you want to protect your app from cross-site request forgery. Maybe you want to authenticate requests before your app runs. Middleware is perfect for these scenarios.

您可以在slim应用程序之前和之后运行代码,以根据需要操作请求和响应对象。这称为中间件。你为什么要这么做?也许您想保护您的应用程序免受跨站点请求伪造。也许您想在应用程序运行之前对请求进行身份验证。中间件非常适合这些场景。

什么是中间件

Technically speaking, a middleware is a callable that accepts three arguments:

从技术上讲,中间件是一个可调用的,它接受三个参数:

  1. \Psr\Http\Message\ServerRequestInterface - The PSR7 request object
  2. \Psr\Http\Message\ResponseInterface - The PSR7 response object
  3. callable - The next middleware callable

It can do whatever is appropriate with these objects. The only hard requirement is that a middleware MUST return an instance of \Psr\Http\Message\ResponseInterface. Each middleware SHOULD invoke the next middleware and pass it Request and Response objects as arguments.

它可以对这些对象做任何适当的操作。唯一困难的要求是中间件必须返回\Psr\Http\Message\ResponseInterface的实例。每个中间件都应该调用下一个中间件,并将请求和响应对象作为参数传递给它。

中间件如何工作?

Different frameworks use middleware differently. Slim adds middleware as concentric layers surrounding your core application. Each new middleware layer surrounds any existing middleware layers. The concentric structure expands outwardly as additional middleware layers are added.The last middleware layer added is the first to be executed.

不同的框架使用中间件的方式不同。Slim将中间件添加为围绕核心应用程序的同心层。每个新的中间件层都围绕着任何现有的中间件层。随着附加中间件层的添加,同心结构向外扩展。添加的最后一个中间件层是要执行的第一个中间件层。

When you run the Slim application, the Request and Response objects traverse the middleware structure from the outside in. They first enter the outer-most middleware, then the next outer-most middleware, (and so on), until they ultimately arrive at the Slim application itself. After the Slim application dispatches the appropriate route, the resultant Response object exits the Slim application and traverses the middleware structure from the inside out. Ultimately, a final Response object exits the outer-most middleware, is serialized into a raw HTTP response, and is returned to the HTTP client. Here’s a diagram that illustrates the middleware process flow:

当您运行Slim应用程序时,请求和响应对象从外向内遍历中间件结构。它们首先进入最外层的中间件,然后进入下一个最外层的中间件,(依此类推),直到最终到达Slim应用程序本身。Slim应用程序分派适当的路由后,生成的响应对象退出Slim应用程序,并从内到外遍历中间件结构。最终,最终的响应对象退出最外层的中间件,序列化为原始HTTP响应,并返回给HTTP客户机。下图演示了中间件流程流程:

如何编写中间件?

Middleware is a callable that accepts three arguments: a Request object, a Response object, and the next middleware. Each middleware MUST return an instance of \Psr\Http\Message\ResponseInterface.

中间件是一个可调用的,它接受三个参数:请求对象、响应对象和下一个中间件。每个中间件必须返回一个\Psr\Http\Message\ResponseInterface实例。

闭包中间件示例

This example middleware is a Closure.

这个中间件示例是一个闭包。

<?php
/**
 * Example middleware closure
 *
 * @param  \Psr\Http\Message\ServerRequestInterface $request  PSR7 request
 * @param  \Psr\Http\Message\ResponseInterface      $response PSR7 response
 * @param  callable                                 $next     Next middleware
 *
 * @return \Psr\Http\Message\ResponseInterface
 */
function ($request, $response, $next) {
    $response->getBody()->write('BEFORE');
    $response = $next($request, $response);
    $response->getBody()->write('AFTER');

    return $response;
};
复制代码

调用类中间件的例子

This example middleware is an invokable class that implements the magic __invoke() method.

这个示例中间件是一个可调用的类,它实现了魔术方法_invoke()。

<?php
class ExampleMiddleware
{
    /**
     * Example middleware invokable class
     *
     * @param  \Psr\Http\Message\ServerRequestInterface $request  PSR7 request
     * @param  \Psr\Http\Message\ResponseInterface      $response PSR7 response
     * @param  callable                                 $next     Next middleware
     *
     * @return \Psr\Http\Message\ResponseInterface
     */
    public function __invoke($request, $response, $next)
    {
        $response->getBody()->write('BEFORE');
        $response = $next($request, $response);
        $response->getBody()->write('AFTER');

        return $response;
    }
}
复制代码

To use this class as a middleware, you can use ->add( new ExampleMiddleware() ); function chain after the app, Route, or group(), which in the code below, any one of these, could representsubject.

要将该类用作中间件,可以使用->add(new ExampleMiddleware());app、Route或group()后面的函数链,在下面的代码中,其中任何一个都可以表示subject。

$subject->add( new ExampleMiddleware() );
复制代码

如何添加中间件?

You may add middleware to a Slim application, to an individual Slim application route or to a route group. All scenarios accept the same middleware and implement the same middleware interface.

您可以向slim应用程序、单个slim应用程序路由或路由组添加中间件。所有场景都接受相同的中间件并实现相同的中间件接口。

应用程序中间件

Application middleware is invoked for every incoming HTTP request. Add application middleware with the Slim application instance’s add() method. This example adds the Closure middleware example above:

为每个传入的HTTP请求调用应用程序中间件。使用Slim应用程序实例的Add()方法添加应用程序中间件。这个例子添加了上面的闭包中间件例子:

<?php
$app = new \Slim\App();

$app->add(function ($request, $response, $next) {
	$response->getBody()->write('BEFORE');
	$response = $next($request, $response);
	$response->getBody()->write('AFTER');

	return $response;
});

$app->get('/', function ($request, $response, $args) {
	$response->getBody()->write(' Hello ');

	return $response;
});

$app->run();
复制代码

This would output this HTTP response body:

这将输出这个HTTP响应体:

BEFORE Hello AFTER
复制代码

路由中间件

Route middleware is invoked only if its route matches the current HTTP request method and URI. Route middleware is specified immediately after you invoke any of the Slim application’s routing methods (e.g., get() or post()). Each routing method returns an instance of \Slim\Route, and this class provides the same middleware interface as the Slim application instance. Add middleware to a Route with the Route instance’s add() method. This example adds the Closure middleware example above:

只有当路由匹配当前HTTP请求方法和URI时,才调用路由中间件。路由中间件是在您调用任何Slim应用程序的路由方法(例如get()或post()之后立即指定的。每个路由方法返回一个\Slim\Route实例,该类提供与Slim应用程序实例相同的中间件接口。使用Route实例的Add()方法向路由添加中间件。这个例子添加了上面的闭包中间件例子:

<?php
$app = new \Slim\App();

$mw = function ($request, $response, $next) {
    $response->getBody()->write('BEFORE');
    $response = $next($request, $response);
    $response->getBody()->write('AFTER');

    return $response;
};

$app->get('/', function ($request, $response, $args) {
	$response->getBody()->write(' Hello ');

	return $response;
})->add($mw);

$app->run();

复制代码

This would output this HTTP response body:

BEFORE Hello AFTER
复制代码

组中间件

In addition to the overall application, and standard routes being able to accept middleware, the group() multi-route definition functionality, also allows individual routes internally. Route group middleware is invoked only if its route matches one of the defined HTTP request methods and URIs from the group. To add middleware within the callback, and entire-group middleware to be set by chaining add() after the group() method.

除了整个应用程序和能够接受中间件的标准路由之外,group()多路由定义功能还允许内部使用单个路由。路由组中间件仅在其路由匹配组中定义的HTTP请求方法和uri之一时才调用。在回调函数中添加中间件,并在group()方法后面链接add()设置要设置的实体组中间件。

Sample Application, making use of callback middleware on a group of url-handlers

<?php

require_once __DIR__.'/vendor/autoload.php';

$app = new \Slim\App();

$app->get('/', function ($request, $response) {
    return $response->getBody()->write('Hello World');
});

$app->group('/utils', function () use ($app) {
    $app->get('/date', function ($request, $response) {
        return $response->getBody()->write(date('Y-m-d H:i:s'));
    });
    $app->get('/time', function ($request, $response) {
        return $response->getBody()->write(time());
    });
})->add(function ($request, $response, $next) {
    $response->getBody()->write('It is now ');
    $response = $next($request, $response);
    $response->getBody()->write('. Enjoy!');

    return $response;
});
复制代码

When calling the /utils/date method, this would output a string similar to the below

It is now 2015-07-06 03:11:01. Enjoy!
复制代码

visiting /utils/time would output a string similar to the below

It is now 1436148762. Enjoy!
复制代码

but visiting / (domain-root), would be expected to generate the following output as no middleware has been assigned

Hello World
复制代码

从中间件传递变量

The easiest way to pass attributes from middleware is to use the request’s attributes.

从中间件传递属性的最简单方法是使用请求的属性。

Setting the variable in the middleware:

$request = $request->withAttribute('foo', 'bar');
复制代码

Getting the variable in the route callback:

$foo = $request->getAttribute('foo');
复制代码

寻找可用的中间件

You may find a PSR 7 Middleware class already written that will satisfy your needs. Here are a few unofficial lists to search.

您可能会发现已经编写好的PSR 7中间件类将满足您的需求。以下是一些可以搜索的非官方列表。

依赖容器(Dependency Container)

Slim uses a dependency container to prepare, manage, and inject application dependencies. Slim supports containers that implement PSR-11 or the Container-Interop interface. You can use Slim’s built-in container (based on [Pimple[(pimple.sensiolabs.org/)) or third-party containers like Acclimate or PHP-DI.

Slim使用依赖容器来准备、管理和注入应用程序依赖项。Slim支持实现PSR-11或容器互操作接口的容器。您可以使用Slim的内置容器(基于piple)或第三方容器,如Acclimate或PHP-DI。

How to use the container

You don’t have to provide a dependency container. If you do, however, you must inject the container instance into the Slim application’s constructor.

您不需要提供依赖容器。但是,如果这样做,则必须将容器实例注入Slim应用程序的构造函数。

$container = new \Slim\Container;
$app = new \Slim\App($container);
复制代码

Add a service to Slim container:

$container = $app->getContainer();
$container['myService'] = function ($container) {
    $myService = new MyService();
    return $myService;
};
复制代码

You can fetch services from your container explicitly or implicitly. You can fetch an explicit reference to the container instance from inside a Slim application route like this:

您可以显式或隐式地从容器中获取服务。您可以从slim应用程序路由中获取对容器实例的显式引用,如下所示:

/**
 * Example GET route
 *
 * @param  \Psr\Http\Message\ServerRequestInterface $req  PSR7 request
 * @param  \Psr\Http\Message\ResponseInterface      $res  PSR7 response
 * @param  array                                    $args Route parameters
 *
 * @return \Psr\Http\Message\ResponseInterface
 */
$app->get('/foo', function ($req, $res, $args) {
    $myService = $this->get('myService');

    return $res;
});
复制代码

You can implicitly fetch services from the container like this:

您可以像这样隐式地从容器中获取服务:

/**
 * Example GET route
 *
 * @param  \Psr\Http\Message\ServerRequestInterface $req  PSR7 request
 * @param  \Psr\Http\Message\ResponseInterface      $res  PSR7 response
 * @param  array                                    $args Route parameters
 *
 * @return \Psr\Http\Message\ResponseInterface
 */
$app->get('/foo', function ($req, $res, $args) {
    $myService = $this->myService;

    return $res;
});
复制代码

To test if a service exists in the container before using it, use the has() method, like this:

要在使用容器之前测试容器中是否存在服务,可以使用has()方法,如下所示:

/**
 * Example GET route
 *
 * @param  \Psr\Http\Message\ServerRequestInterface $req  PSR7 request
 * @param  \Psr\Http\Message\ResponseInterface      $res  PSR7 response
 * @param  array                                    $args Route parameters
 *
 * @return \Psr\Http\Message\ResponseInterface
 */
$app->get('/foo', function ($req, $res, $args) {
    if($this->has('myService')) {
        $myService = $this->myService;
    }

    return $res;
});
复制代码

Slim uses __get() and __isset() magic methods that defer to the application’s container for all properties that do not already exist on the application instance.

Slim使用了_get()和_isset()魔法方法,这些方法根据应用程序容器处理应用程序实例上不存在的所有属性。

要求的服务

Your container MUST implement these required services. If you use Slim’s built-in container, these are provided for you. If you choose a third-party container, you must define these required services on your own.

您的容器必须实现这些必需的服务。如果您使用Slim的内置容器,就会得到这些。如果选择第三方容器,则必须自己定义这些必需的服务。

设置

Associative array of application settings, including keys:

应用程序设置的关联数组,包括键:

  • httpVersion
  • responseChunkSize
  • outputBuffering
  • determineRouteBeforeAppMiddleware.
  • displayErrorDetails.
  • addContentLengthHeader.
  • routerCacheFile.
environment

Instance of \Slim\Interfaces\Http\EnvironmentInterface.

request

Instance of \Psr\Http\Message\ServerRequestInterface.

response

Instance of \Psr\Http\Message\ResponseInterface.

router

Instance of \Slim\Interfaces\RouterInterface.

foundHandler

Instance of \Slim\Interfaces\InvocationStrategyInterface.

phpErrorHandler

Callable invoked if a PHP 7 Error is thrown. The callable MUST return an instance of \Psr\Http\Message\ResponseInterface and accept three arguments:

  1. \Psr\Http\Message\ServerRequestInterface
  2. \Psr\Http\Message\ResponseInterface
  3. \Error
errorHandler

Callable invoked if an Exception is thrown. The callable MUST return an instance of \Psr\Http\Message\ResponseInterface and accept three arguments:

  1. \Psr\Http\Message\ServerRequestInterface
  2. \Psr\Http\Message\ResponseInterface
  3. \Exception
notFoundHandler

Callable invoked if the current HTTP request URI does not match an application route. The callable MUST return an instance of \Psr\Http\Message\ResponseInterface and accept two arguments:

  1. \Psr\Http\Message\ServerRequestInterface
  2. \Psr\Http\Message\ResponseInterface
notAllowedHandler

Callable invoked if an application route matches the current HTTP request path but not its method. The callable MUST return an instance of

  1. \Psr\Http\Message\ResponseInterface and accept three arguments:
  2. \Psr\Http\Message\ServerRequestInterface
  3. \Psr\Http\Message\ResponseInterface
  4. Array of allowed HTTP methods
callableResolver

Instance of \Slim\Interfaces\CallableResolverInterface.

转载于:https://juejin.im/post/5cad99e85188251ade3d9ae4

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值