HttpFoundation组件

编辑本页

警告:您正在浏览的文档欧宝体育电话欧宝娱乐app下载地址Symfony 5.2,现已不再维护。

本页的更新版本用于Sy欧宝娱乐app下载地址mfony 6.2(当前稳定版本)。

HttpFoundation组件

在深入研究框架创建过程之前,让我们先退一步,看看为什么希望使用框架,而不是保持普通的PHP应用程序不变。为什么使用框架实际上是一个好主意,甚至对于最简单的代码片段也是如此,以及为什么在Symfony组件之上创建框架比从头创建框架更好。欧宝娱乐app下载地址

请注意

我们不会讨论与多个开发人员一起开发大型应用程序时使用框架的传统好处;互联网上已经有很多关于这个话题的好资源。

即使我们在前一章中写的“应用程序”足够简单,它也存在一些问题:

1 2 3 4
/ /框架/ index . php的名字_GET“名字”];printf (“你好% s”的名字);

首先,如果的名字query参数没有在URL查询字符串中定义,你会得到一个PHP警告;所以让我们来解决这个问题:

1 2 3 4
/ /框架/ index . php的名字_GET“名字”) ? ?“世界”;printf (“你好% s”的名字);

然后,这应用程序不安全.你能相信吗?即使是这个简单的PHP代码片段也容易受到最广泛的互联网安全问题之一XSS(跨站点脚本)的攻击。下面是一个更安全的版本:

1 2 3 4 5
的名字_GET“名字”) ? ?“世界”;头(内容类型:text / html;charset = utf - 8 ');printf (“你好% s”,:的名字ENT_QUOTES,“utf - 8”));

请注意

您可能已经注意到,使用htmlspecialchars函数冗长且容易出错。这就是为什么使用模板引擎的原因之一嫩枝,其中自动转义在默认情况下是启用的,这可能是一个好主意(而且显式转义使用simple . xml也不那么痛苦e过滤器)。

正如您所看到的,如果我们希望避免PHP警告/注意并使代码更安全,那么我们首先编写的简单代码就不再那么简单了。

除了安全性之外,这段代码测试起来可能很复杂。即使没有太多要测试的东西,我还是觉得为尽可能简单的PHP代码段编写单元测试是不自然的,而且感觉很难看。下面是上面代码的PHPUnit单元测试:

12 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/ /框架/ test.php使用PHPUnit)框架TestCaseIndexTest扩展TestCase公共函数testHello()_GET“名字”] =“法”;ob_start ();包括“index . php”内容= ob_get_clean ();->assertequal (“你好法”内容);}}

请注意

如果我们的应用程序稍微大一点,我们就能发现更多的问题。如果你对它们感兴趣,请阅读欧宝娱乐app下载地址Symfony vs . Flat PHP书中的章节。

在这一点上,如果您不相信安全性和测试确实是停止以旧方式编写代码并转而采用框架的两个非常好的理由(无论在此上下文中采用框架意味着什么),那么您现在可以停止阅读本书,回到您以前正在编写的代码中。

请注意

使用框架应该给您带来的不仅仅是安全性和可测试性,但更重要的是要记住,您选择的框架必须允许您更快地编写更好的代码。

使用HttpFoundation组件进行面向对象编程

编写web代码是关于与HTTP交互的。因此,我们框架的基本原则应该围绕HTTP规范

HTTP规范描述了客户端(例如浏览器)如何与服务器(我们的应用程序通过web服务器)交互。客户端和服务器之间的对话由定义良好的消息、请求和响应:客户端向服务器发送请求,服务器根据该请求返回响应

在PHP中,请求由全局变量($ _GET$ _POST带有_FILE美元_COOKIE美元_SESSION美元…),响应由函数(回声setcookie,……)。

实现更好的代码的第一步可能是使用面向对象的方法;这就是Symfony HttpFoundation组件的欧宝娱乐app下载地址主要目标:用面向对象层替换默认的PHP全局变量和函数。

要使用此组件,将其添加为项目的依赖项:

1
作曲家需要symfony/http欧宝娱乐app下载地址-foundation

运行此命令还将自动下载Symfony HttpFoundation组件并将其安装在欧宝娱乐app下载地址供应商/目录中。一个composer.json和一个composer.lock也将生成包含新需求的文件。

在安装新的依赖项时,Composer还会生成一个供应商/ autoload.php文件,该文件允许任意类自动装载.在没有自动加载的情况下,在能够使用类之前,您将需要使用定义类的文件。但是多亏了PSR-4,我们可以让Composer和PHP为我们做艰苦的工作。

方法重写应用程序请求响应类:

12 3 4 5 6 7 8 9 10 11 12 13
/ /框架/ index . phprequire_once__DIR__“/供应商/ autoload.php”使用欧宝娱乐app下载地址组件HttpFoundation请求使用欧宝娱乐app下载地址组件HttpFoundation响应请求=请求::createFromGlobals ();的名字请求->get (“名字”“世界”);响应响应(sprintf (“你好% s”,:的名字ENT_QUOTES,“utf - 8”)));响应->send ();

createFromGlobals ()方法创建请求对象基于当前PHP全局变量。

send ()方法将响应对象返回给客户端(它首先输出HTTP报头,然后输出内容)。

提示

之前send ()调用,我们应该添加一个调用到准备()方法(反应- >准备美元($请求);),以确保我们的响应符合HTTP规范。例如,如果我们使用方法,它将删除响应的内容。

与前面代码的主要区别在于,您可以完全控制HTTP消息。您可以创建您想要的任何请求,并负责在您认为合适的时候发送响应。

请注意

我们还没有显式地设置内容类型头,作为响应对象的默认字符集utf - 8

请求类,你有所有的请求信息在你的指尖感谢一个漂亮和简单的API:

12 3 4 5 6 7 8 9 10 11 12 13 14 16 17 18 19 20 21 22
//被请求的URI(例如/about)减去任何查询参数请求->getPathInfo ();//分别获取GET和POST变量请求->查询->get (“foo”);请求->请求->get (“酒吧”'如果bar不存在,则默认值');//检索SERVER变量请求->服务器->get (“HTTP_HOST”);//获取一个由foo标识的UploadedFile实例请求->文件->get (“foo”);//获取COOKIE值请求->饼干->get (“PHPSESSID”);//检索一个HTTP请求头,带有规范化的小写键请求->->get (“主机”);请求->->get (“内容类型”);请求->getMethod ();// get, post, put, delete, head请求->getLanguages ();//客户端接受的语言数组

你也可以模拟一个请求:

1
请求=请求::创建(' / index . php ?name =法”);

响应类,您可以调整响应:

1 2 3 4 5 6 7 8
响应反应();响应->setContent (“Hello world !”);响应->setStatusCode (200);响应->->集(“内容类型”“text / html”);//配置HTTP缓存头响应->setMaxAge (10);

提示

要调试响应,将其转换为字符串;它将返回响应的HTTP表示形式(头和内容)。

最后但并非最不重要的是,这些类与Symfony代码中的其他类一样,已经被删除了欧宝娱乐app下载地址经审计的安全问题由独立公司处理。作为一个开源项目也意味着世界各地的许多其他开发人员已经阅读了代码,并已经修复了潜在的安全问题。您上一次为您的自制框架订购专业安全审计是什么时候?

即使是像获取客户端IP地址这样简单的事情也可能是不安全的:

1 2 3
如果myIp= = =_SERVER“REMOTE_ADDR”) {//客户端是已知的,所以给它更多的特权

它工作得非常好,直到您在生产服务器前添加一个反向代理;在这一点上,你必须改变你的代码,使它在你的开发机器(你没有代理)和你的服务器上工作:

1 2 3
如果myIp= = =_SERVER“HTTP_X_FORWARDED_FOR”) | |myIp= = =_SERVER“REMOTE_ADDR”) {//客户端是已知的,所以给它更多的特权

使用要求::getClientIp ()方法将从第一天开始就为您提供正确的行为(并且它将涵盖您有链式代理的情况):

1 2 3 4 5
请求=请求::createFromGlobals ();如果myIp= = =请求->getClientIp ()) {//客户端是已知的,所以给它更多的特权

而且还有一个额外的好处:它确实是安全默认情况下。这是什么意思?的$ _SERVER(“HTTP_X_FORWARDED_FOR”)值不可信,因为在没有代理的情况下,最终用户可以操纵它。因此,如果在没有代理的情况下在生产环境中使用此代码,那么很容易滥用您的系统。不是这样的getClientIp ()方法,因为您必须通过调用显式信任反向代理setTrustedProxies ()

1 2 3 4 5
请求::setTrustedProxies ([“10.0.0.1”表示]);如果myIp= = =请求->getClientIp ()) {//客户端是已知的,所以给它更多的特权

所以,getClientIp ()方法在所有情况下都安全工作。您可以在所有项目中使用它,无论配置是什么,它都将正确且安全地运行。这是使用框架的目标之一。如果您要从头开始编写一个框架,那么您将不得不自己考虑所有这些情况。为什么不使用现有的技术呢?

请注意

如果你想了解更多关于HttpFoundation组件的知识,你可以看看HttpFoundation组件欧宝娱乐app下载地址Symfony \ \ HttpFoundation组件API或读取其专用欧宝体育电话

信不信由你,我们已经有了第一个框架。如果你愿意,现在就可以停下来。仅使用Symfony Http欧宝娱乐app下载地址Foundation组件已经允许您编写更好、更可测试的代码。它还允许您更快地编写代码,因为许多日常问题已经为您解决了。

事实上,像Drupal这样的项目已经采用了HttpFoundation组件;如果对他们有效,对你也可能有效。不要白费力气。

我几乎忘了说一个额外的好处:使用HttpFoundation组件是所有框架和框架之间更好的互操作性的开始应用程序使用它(如欧宝娱乐app下载地址Drupal 8phpBB 3Laravel而且ezPublish 5,更多的).

此工作,包括代码示例,是根据创作共用BY-SA 3.0许可证。