教科书般的PHP框架学习指南php
注:翻译水平有限,若有错误,欢迎指正html
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.ios
Slim为其请求和响应对象支持PSR-7接口。这使得Slim很是灵活,由于它可使用任何PSR-7实现。例如,Slim应用程序路由没必要返回\Slim\Http\Response的实例。例如,它能够返回\GuzzleHttp\Psr7\CachingStream的实例,或者\GuzzleHttp\Psr7\stream_for()函数返回的任何实例。git
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.github
Slim提供了本身的PSR-7实现,所以能够开箱即用。不过,您可使用第三方实现替换Slim的默认PSR 7对象。只需覆盖应用程序容器的请求和响应服务,以便它们分别返回\Psr\Http\Message\ServerRequestInterface和\Psr\Http\Message\ResponseInterface的实例。json
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的请求和响应对象是不可变的值对象。它们只能经过请求具备更新属性值的克隆版原本“更改”。值对象具备名义开销,由于必须在更新属性时克隆它们。这种开销不会对性能产生实质性的影响。bash
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(value) method that returns a cloned value object with the new HTTP header.cookie
您能够经过调用值对象的任何PSR 7接口方法来请求值对象的副本(这些方法一般具备带前缀的方法)。例如,PSR 7响应对象有一个withHeader(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接口提供了这些方法来转换请求和响应对象:
The PSR 7 interface provides these methods to transform Request objects:
PSR 7接口提供了如下方法来转换请求对象:
The PSR 7 interface provides these methods to transform Response objects:
PSR 7接口提供了如下方法来转换响应对象:
Refer to the PSR-7 documentation for more information about these methods. 有关这些方法的更多信息,请参阅PSR-7文档。
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:
从技术上讲,中间件是一个可调用的,它接受三个参数:
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 subject.
要将该类用做中间件,可使用->add(new ExampleMiddleware());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中间件类将知足您的需求。如下是一些能够搜索的非官方列表。
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。
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:
应用程序设置的关联数组,包括键:
Instance of \Slim\Interfaces\Http\EnvironmentInterface.
Instance of \Psr\Http\Message\ServerRequestInterface.
Instance of \Psr\Http\Message\ResponseInterface.
Instance of \Slim\Interfaces\RouterInterface.
Instance of \Slim\Interfaces\InvocationStrategyInterface.
Callable invoked if a PHP 7 Error is thrown. The callable MUST return an instance of \Psr\Http\Message\ResponseInterface and accept three arguments:
Callable invoked if an Exception is thrown. The callable MUST return an instance of \Psr\Http\Message\ResponseInterface and accept three arguments:
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:
Callable invoked if an application route matches the current HTTP request path but not its method. The callable MUST return an instance of
Instance of \Slim\Interfaces\CallableResolverInterface.