教科书般的PHP框架学习指南
注:翻译水平有限,如有错误,欢迎指正
关于Slim
Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs. At its core, Slim is a dispatcher that receives an HTTP request, invokes an appropriate callback routine, and returns an HTTP response. That’s it.
Slim是一个PHP微框架,可以帮助您快速编写简单但功能强大的web应用程序和api。Slim的核心是一个dispatcher(调度器),它接收HTTP请求,调用适当的回调例程,并返回HTTP响应。就是这样。
价值
Slim is an ideal tool to create APIs that consume, repurpose, or publish data. Slim is also a great tool for rapid prototyping. Heck, you can even build full-featured web applications with user interfaces. More importantly, Slim is super fast and has very little code. In fact, you can read and understand its source code in only an afternoon!
Slim是消费、重用或发布数据的理想API工具。Slim也是快速原型制作的一个很好的工具。见鬼,您甚至可以使用用户界面构建功能齐全的web应用程序。更重要的是,Slim速度非常快,代码很少。事实上,您只需一个下午就可以阅读和理解它的源代码!
You don’t always need a kitchen-sink solution like Symfony or Laravel. These are great tools, for sure. But they are often overkill. Instead, Slim provides only a minimal set of tools that do what you need and nothing else.
你并不总是需要像Symfony或Laravel那么激进的解决方案。毫无疑问,这些都是很棒的工具。但它们往往是矫枉过正。相反,Slim只提供了一组最小的工具,它们只做您需要的事情,而不做其他任何事情。
如何工作?
First, you need a web server like Nginx or Apache. You should configure your web server so that it sends all appropriate requests to one “front-controller” PHP file. You instantiate and run your Slim app in this PHP file.
A Slim app contains routes that respond to specific HTTP requests. Each route invokes a callback and returns an HTTP response. To get started, you first instantiate and configure the Slim application. Next, you define your application routes. Finally, you run the Slim application. It’s that easy. Here’s an example application:
首先,您需要像Nginx或Apache这样的web服务器。您应该配置您的web服务器,以便它将所有适当的请求发送到一个“前端控制器”PHP文件。在这个PHP文件中实例化并运行Slim应用程序。
slim应用程序包含响应特定HTTP请求的路由。每个路由调用一个回调并返回一个HTTP响应。首先,您要实例化并配置Slim应用程序。接下来,定义应用程序路由。最后,运行Slim应用程序。它是那么容易。下面是一个应用程序示例:
$config = ['settings' => [
'addContentLengthHeader' => false,
]];
$app = new \Slim\App($config);
// Define app routes
$app->get('/hello/{name}', function ($request, $response, $args) {
return $response->write("Hello " . $args['name']);
});
// Run app
$app->run();
复制代码
请求和相应
When you build a Slim app, you are often working directly with Request and Response objects. These objects represent the actual HTTP request received by the web server and the eventual HTTP response returned to the client.
Every Slim app route is given the current Request and Response objects as arguments to its callback routine. These objects implement the popular PSR 7 interfaces. The Slim app route can inspect or manipulate these objects as necessary. Ultimately, each Slim app route MUST return a PSR 7 Response object.
当您构建一个Slim应用程序时,您经常直接处理请求和响应对象。这些对象表示web服务器接收到的实际HTTP请求和返回给客户机的最终HTTP响应。
每个Slim应用程序路由都将当前请求和响应对象作为其回调例程的参数。这些对象实现了流行的PSR 7接口。Slim应用程序路由可以根据需要检查或操作这些对象。最终,每个Slim应用程序路由必须返回一个PSR 7响应对象。
引入自己的组件
Slim is designed to play well with other PHP components, too. You can register additional first-party components such as Slim-Csrf, Slim-HttpCache, or Slim-Flash that build upon Slim’s default functionality. It’s also easy to integrate third-party components found on Packagist.
Slim还可以很好地与其他PHP组件配合使用。您可以额外注册基于Slim默认功能的自有组件,如Slim-csrf、Slim-httpcache或Slim-flash。或者集成Packagist上的第三方组件也很容易。
如何阅读此文档
If you are new to Slim, I recommend you read this documentation from start to finish. If you are already familiar with Slim, you can instead jump straight to the appropriate section.
如果您是Slim的新手,我建议您从头到尾阅读本文。如果您已经熟悉Slim,则可以直接跳到相应的部分。
This documentation begins by explaining Slim’s concepts and architecture before venturing into specific topics like request and response handling, routing, and error handling.
本文档首先解释Slim的概念和体系结构,然后讨论请求和响应处理、路由和错误处理等特定主题。
安装
系统要求
Web server with URL rewriting
PHP 5.5 or newer
复制代码
如何安装slim
We recommend you install Slim with Composer. Navigate into your project’s root directory and execute the bash command shown below. This command downloads the Slim Framework and its third-party dependencies into your project’s vendor/ directory.
我们建议您使用Composer安装Slim。导航到项目的根目录并执行如下所示的bash命令。此命令将Slim框架及其第三方依赖项下载到项目的vendor/目录中。
composer require slim/slim "^3.0"
复制代码
Require the Composer autoloader into your PHP script, and you are ready to start using Slim.
'vendor/autoload.php';
复制代码
升级说明
New PHP version
Slim 3 requires PHP 5.5+
复制代码
Class \Slim\Slim renamed \Slim\App
Slim 3 uses \Slim\App for the Application object usually named $app.
$app = new \Slim\App();
复制代码
新的路由函数特性
$app->get('/', function (Request $req, Response $res, $args = []) {
return $res->withStatus(400)->write('Bad Request');
});
复制代码
请求和响应对象不能再通过App对象直接访问
As mentioned above, Slim 3 passes the Request and Response objects as arguments to the route handling function. Since they are now accessible directly in the body of a route function, request and response are no longer properties of the /Slim/App (Application object) instance.
如上所述,Slim 3将请求和响应对象作为参数传递给路由处理函数。由于它们现在可以在route函数体中直接访问,请求和响应不再是/Slim/App(应用程序对象)实例的属性。
获取_GET和_POST变量
$app->get('/', function (Request $req, Response $res, $args = []) {
$myvar1 = $req->getParam('myvar'); //checks both _GET and _POST [NOT PSR-7 Compliant]
$myvar2 = $req->getParsedBody()['myvar']; //checks _POST [IS PSR-7 compliant]
$myvar3 = $req->getQueryParams()['myvar']; //checks _GET [IS PSR-7 compliant]
});
复制代码
钩子
Hooks are no longer part of Slim as of v3. You should consider reimplementing any functionality associated with the default hooks in Slim v2 as middleware instead. If you need the ability to apply custom hooks at arbitrary points in your code (for example, within a route), you should consider a third-party package such as Symfony’s EventDispatcher or Zend Framework’s EventManager.
钩子在v3中不再是Slim的一部分。您应该考虑将Slim v2中与缺省钩子相关的任何功能重新实现为中间件。如果您需要在代码中的任意点应用自定义钩子的能力(例如,在路由中),您应该考虑第三方包,如Symfony的EventDispatcher或Zend Framework的EventManager。
HTTP缓存迁移
In Slim v3 we have removed the HTTP-Caching into its own module Slim\Http\Cache.
在Slim v3中,我们已经将Http缓存迁移到它自己的模块Slim\Http\Cache中。
Stop/Halt被移除
Slim Core has removed Stop/Halt. In your applications, you should transition to using the withStatus() and withBody() methods.
Slim内核已删除Stop/Halt。在应用程序中,应该过渡到使用withStatus()和withBody()方法。
取消自动加载器
为什么有些框架越来越复杂,因为里面充斥着过时的代码,混淆了开发者,及时清理很重要,保持简单,避免出现重复的轮子
Slim::registerAutoloader() have been removed, we have fully moved to composer.
Slim: registerAutoloader()已被删除,我们已经完全迁移到composer。
容器的修改(V3的容器组件基于piple构建)
$app->container->singleton(...) is now $container = $app->getContainer();
$container['...'] = function () {};
Please read Pimple docs for more info
复制代码
移除了configureMode()
$app->configureMode(...) has been removed in v3.
移除了PrettyExceptions
PrettyExceptions cause lots of issues for many people, so these have been removed. 漂亮的异常会给很多人带来很多问题,所以这些已经被删除了。
移除了Route::setDefaultConditions(…)
We have switched routers which enable you to keep the default conditions regex inside of the route pattern.
重定向的修改
In Slim v2.x one would use the helper function $app->redirect(); to trigger a redirect request. In Slim v3.x one can do the same with using the Response class like so.
在Slim v2.x 使用助手函数$app->redirect();触发重定向请求。在Slim v3.x 使用Response类也可以这样做。
Example:
$app->get('/', function ($req, $res, $args) {
return $res->withStatus(302)->withHeader('Location', 'your-new-uri');
});
Alternatively, if you want a route to redirect without any other handling, you can use the shortcut helper function $app->redirect() as the route definition:
$app->redirect('/', 'your-new-uri');
复制代码
新的中间件特性
The middleware signature has changed from a class to a function.
中间件特性已从类更改为函数。
New signature:
use Psr\Http\Message\RequestInterface as Request;
use Psr\Http\Message\ResponseInterface as Response;
$app->add(function (Request $req, Response $res, callable $next) {
// Do stuff before passing along
$newResponse = $next($req, $res);
// Do stuff after route is rendered
return $newResponse; // continue
});
复制代码
You can still use a class:
namespace My;
use Psr\Http\Message\RequestInterface as Request;
use Psr\Http\Message\ResponseInterface as Response;
class Middleware
{
function __invoke(Request $req, Response $res, callable $next) {
// Do stuff before passing along
$newResponse = $next($req, $res);
// Do stuff after route is rendered
return $newResponse; // continue
}
}
// Register
$app->add(new My\Middleware());
// or
$app->add(My\Middleware::class);
复制代码
执行中间件
Application middleware is executed as Last In First Executed (LIFE).
应用程序首次被执行时,中间件被放在了最后执行
Flash消息
Flash messages are no longer a part of the Slim v3 core but instead have been moved to seperate Slim Flash package.
Flash消息不再是Slim v3核心的一部分,而是被迁移成了独立的Slim Flash包。
Cookies
In v3.0 cookies has been removed from core. See FIG Cookies for a PSR-7 compatible cookie component.
在v3.0中cookies已经从核心中移除。参见FIG Cookies了解PSR-7兼容的cookie组件。
移除了Crypto
In v3.0 we have removed the dependency for crypto in core.
在v3.0中,我们已经消除了Crypto的依赖。
新的路由
Slim now utilizes FastRoute, a new, more powerful router!
This means that the specification of route patterns has changed with named parameters now in braces and square brackets used for optional segments:
Slim现在利用FastRoute,一个新的,更强大的路由器!
这意味着路由模式的规范已经发生了变化,命名参数现在在大括号和方括号中用于可选段:
// named parameter:
$app->get('/hello/{name}', /*...*/);
// optional segment:
$app->get('/news[/{year}]', /*...*/);
复制代码
路由中间件
The syntax for adding route middleware has changed slightly. In v3.0:
添加路由中间件的语法略有变化。在v3.0:
$app->get(…)->add($mw2)->add($mw1);
复制代码
获取当前路由
The route is an attribute of the Request object in v3.0:
路由是v3.0中请求对象的一个属性:
$request->getAttribute('route');
复制代码
When getting the current route in middleware, the value for determineRouteBeforeAppMiddleware must be set to true in the Application configuration, otherwise the getAttribute call returns null.
当在中间件中获取当前路由时,应用程序配置中必须将defineroutebeforeappmiddleware的值设置为true,否则getAttribute调用将返回null。
urlFor()被pathFor()代替
urlFor() has been renamed pathFor() and can be found in the router object:
urlFor()被重命名为pathFor(),可以在router对象中找到:
$app->get('/', function ($request, $response, $args) {
$url = $this->router->pathFor('home');
$response->write("Home");
return $response;
})->setName('home');
复制代码
Also, pathFor() is base path aware.
此外,pathFor()是基本路径感知的。
新的容器解决方案
Slim uses Pimple as a Dependency Injection Container.
Slim使用Pimple作为依赖注入容器。
// index.php
$app = new Slim\App(
new \Slim\Container(
include '../config/container.config.php'
)
);
// Slim will grab the Home class from the container defined below and execute its index method.
// If the class is not defined in the container Slim will still contruct it and pass the container as the first arugment to the constructor!
$app->get('/', Home::class . ':index');
// In container.config.php
// We are using the SlimTwig here
return [
'settings' => [
'viewTemplatesDirectory' => '../templates',
],
'twig' => [
'title' => '',
'description' => '',
'author' => ''
],
'view' => function ($c) {
$view = new Twig(
$c['settings']['viewTemplatesDirectory'],
[
'cache' => false // '../cache'
]
);
// Instantiate and add Slim specific extension
$view->addExtension(
new TwigExtension(
$c['router'],
$c['request']->getUri()
)
);
foreach ($c['twig'] as $name => $value) {
$view->getEnvironment()->addGlobal($name, $value);
}
return $view;
},
Home::class => function ($c) {
return new Home($c['view']);
}
];
复制代码
PSR-7规范下的数据请求和响应
Request, Response, Uri & UploadFile are immutable. This means that when you change one of these objects, the old instance is not updated.
请求、响应、Uri和UploadFile是不可变的。 这意味着当您更改其中一个对象时,旧实例不会更新。
// This is WRONG. The change will not pass through.
$app->add(function (Request $request, Response $response, $next) {
$request->withAttribute('abc', 'def');
return $next($request, $response);
});
// This is correct.
$app->add(function (Request $request, Response $response, $next) {
$request = $request->withAttribute('abc', 'def');
return $next($request, $response);
});
复制代码
消息流
// ...
$image = __DIR__ . '/huge_photo.jpg';
$body = new Stream($image);
$response = (new Response())
->withStatus(200, 'OK')
->withHeader('Content-Type', 'image/jpeg')
->withHeader('Content-Length', filesize($image))
->withBody($body);
// ...
复制代码
For text:
// ...
$response = (new Response())->getBody()->write('Hello world!')
// Or Slim specific: Not PSR-7 compliant.
$response = (new Response())->write('Hello world!');
// ...
复制代码
WEB服务器
It is typical to use the front-controller pattern to funnel appropriate HTTP requests received by your web server to a single PHP file. The instructions below explain how to tell your web server to send HTTP requests to your PHP front-controller file.
通常使用前端控制器模式将web服务器接收到的适当HTTP请求引导到单个PHP文件。下面的说明说明了如何告诉web服务器将HTTP请求发送到PHP前端控制器文件。
PHP内置服务器
Run the following command in terminal to start localhost web server, assuming ./public/ is public-accessible directory with index.php file:
假设./public/是带有index.php文件的公共可访问目录,在终端中运行以下命令启动localhost web服务器:
php -S localhost:8888 -t public public/index.php
复制代码
If you are not using index.php as your entry point then change appropriately.
如果您没有使用index.php作为入口点,那么请进行适当的更改。
Apache配置
Ensure your .htaccess and index.php files are in the same public-accessible directory. The .htaccess file should contain this code:
确保.htaccess和index.php文件位于同一个公共访问目录中。.htaccess文件应该包含以下代码:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [QSA,L]
复制代码
This .htaccess file requires URL rewriting. Make sure to enable Apache’s mod_rewrite module and your virtual host is configured with the AllowOverride option so that the .htaccess rewrite rules can be used:
这个.htaccess文件需要URL重写。请确保启用Apache的mod_rewrite模块,并且您的虚拟主机配置了AllowOverride选项,以便可以使用.htaccess重写规则:
AllowOverride All
复制代码
Nginx配置
This is an example Nginx virtual host configuration for the domain example.com. It listens for inbound HTTP connections on port 80. It assumes a PHP-FPM server is running on port 9000. You should update the server_name, error_log, access_log, and root directives with your own values. The root directive is the path to your application’s public document root directory; your Slim app’s index.php front-controller file should be in this directory.
这是一个为example.com配置的Nginx虚拟主机配置示例。它侦听端口80上的入站HTTP连接。它假设PHP-FPM服务器运行在端口9000上。您应该使用自己的值更新server_name、error_log、access_log和根指令。根指令是应用程序的公共文档根目录的路径;Slim应用程序的index.php前端控制器文件应该在这个目录中。
server {
listen 80;
server_name example.com;
index index.php;
error_log /path/to/example.error.log;
access_log /path/to/example.access.log;
root /path/to/public;
location / {
try_files $uri /index.php$is_args$args;
}
location ~ \.php {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_index index.php;
fastcgi_pass 127.0.0.1:9000;
}
}
复制代码
HipHop虚拟机
Your HipHop Virtual Machine configuration file should contain this code (along with other settings you may need). Be sure you change the SourceRoot setting to point to your Slim app’s document root directory.
您的HipHop虚拟机配置文件应该包含此代码(以及您可能需要的其他设置)。确保将SourceRoot设置更改为指向Slim应用程序的文档根目录。
Server {
SourceRoot = /path/to/public/directory
}
ServerVariables {
SCRIPT_NAME = /index.php
}
VirtualHost {
* {
Pattern = .*
RewriteRules {
* {
pattern = ^(.*)$
to = index.php/$1
qsa = true
}
}
}
}
复制代码
IIS服务器
Ensure the Web.config and index.php files are in the same public-accessible directory. The Web.config file should contain this code:
确保Web.config和index.php文件位于同一个公共访问目录中。Web.config应该包含以下代码:
"1.0" encoding="UTF-8"?>
"slim" patternSyntax="Wildcard">
"*" />
"{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
"{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
type="Rewrite" url="index.php" />
复制代码
lighttpd服务器
Your lighttpd configuration file should contain this code (along with other settings you may need). This code requires lighttpd >= 1.4.24.
您的lighttpd配置文件应该包含此代码(以及您可能需要的其他设置)。这段代码需要lighttpd >= 1.4.24。
url.rewrite-if-not-file = ("(.*)" => "/index.php/$0")
复制代码
This assumes that Slim’s index.php is in the root folder of your project (www root).
这假设Slim的index.php位于项目的根文件夹(www root)中。
部署
Congratulations! if you have made it this far, that means you have successfully built something awesome using Slim. However, the time to party has not come yet. We still have to push our application to the production server.
There are many ways to do this that are beyond the scope of this documentation. In this section, we provide some notes for various set-ups.
恭喜你!如果你已经做到了这一步,那就意味着你已经成功地使用Slim创建了一些很棒的东西。然而,聚会庆祝的时间还没有到。我们仍然必须将应用程序推到生产服务器。
有许多本文档之外的方法同样可以做到这一点。在本节中,我们将为各种设置提供一些注释。
在生产环境关闭错误输出
The first thing to do is to tweak your settings (src/settings.php in the skeleton application) and ensure that you do not display full error details to the public.
首先要做的是调整设置(骨架应用程序中的src/settings.php),并确保不会向公众显示完整的错误细节。
'displayErrorDetails' => false, // set to false in production
复制代码
You should also ensure that your PHP installation is configured to not display errors with the php.ini setting:
display_errors = 0
复制代码
部署在自己的服务器
If you control your server, then you should set up a deployment process using any one of the many deployment system such as:
如果你控制你的伺服器,你应该使用以下任何一个部署系统来建立部署过程:
- Deploybot
- Capistrano
- Script controlled with Phing, Make, Ant, etc.
部署在一个共享服务器
If your shared server runs Apache, then you need to create a .htaccess file in your web server root directory (usually named htdocs, public, public_html or www) with the following content:
如果共享服务器运行Apache,则需要在web服务器根目录(通常名为htdocs、public、public_html或www)中创建一个.htaccess文件,内容如下:
RewriteEngine on
RewriteRule ^$ public/ [L]
RewriteRule (.*) public/$1 [L]
复制代码
(replace ‘public’ with the correct name of your domain name e.g. example.com/$1)
将“public”替换为您的域名的正确名称,例如example.com/$1
Now upload all the files that make up your Slim project to the webserver. As you are on shared hosting, this is probably done via FTP and you can use any FTP client, such as Filezilla to do this.
现在将构成Slim项目的所有文件上传到web服务器。由于您是在共享主机上,这可能是通过FTP完成的,您可以使用任何FTP客户机,比如Filezilla来完成这一任务。