教科書般的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.