恭喜你!经过学习Symfony2,你将用你本身的方式开发出更加高效、全面和流行的Web应用(固然,要受到用人单位或同行的欢迎,仍是得靠你本身)。Symfony2的存在是为了要解决最根本的问题:即提供一个开发工具,使开发者能以本身的方式更快速地开发出更为健壮的应用程序。Symfony2集成了许多技术的优势,包括工具和概念,你将学到大多数人多年来努力的方向。换句话说,你不仅是在学习Symfony2,你还将学习Web基础原理、最佳开发实践以及如何使用许多新的、优秀的PHP开发库。因此,请作好准备!
php
本章将从解释Web开发过程当中最常接触的基础概念开始:HTTP协议。不管技术背景或首选编程语言是什么,本章的内容对于全部人来讲都是必需要了解的。html
HTTP(超文本传输协议)是一个容许两个机器相互通讯的文本语言。举例来讲,当你要去 xkcd 网站查看最新的漫画时,下列会话(近似地)将在你的浏览器和服务器之间发生:前端
虽然实际使用的语言将更加正规,但它依然是很简单的。HTTP定义了这种简单文本语言的语义和语法。而不管你从事何种的Web开发,你的服务器老是要理解基于文本的请求,并返回基于文本的响应。git
Symfony2是基于现实构建的,不管你是否意识到这一点,HTTP都是你天天所需的。随着对Symfony2学习的深刻,你将学会如何掌握它。github
Web上的每一个会话都是从一个请求开始的,这个请求是由客户端(如:网页浏览器、iPhone应用程序等)建立的一种特殊格式的文本消息,该格式符合HTTP协议规范。客户端将该请求发送到服务端,而后等待服务端响应。数据库
下图体现的是,浏览器与xkcd服务器之间交互的第一阶段(请求):编程
以HTTP的方式来讲,HTTP请求就象下面这个样子:数组
GET / HTTP/1.1 Host: xkcd.com Accept: text/html User-Agent: Mozilla/5.0 (Macintosh)
这个简单的消息准确地描述了客户端所请求的究竟是哪一个资源。HTTP请求的第一行是最重要的,它包含了两项信息:URI和HTTP方法。浏览器
URI(如:/、/contact等)代表了客户端所请求资源的惟一地址或位置。HTTP方法(如:GET)则是向服务器说明你想对资源作什么,HTTP方法是请求的“动词”,用以定义你对资源的操做:缓存
GET | 从服务器上检索资源 |
POST | 在服务器上建立一个资源 |
UPDATE | 更新服务器上的资源 |
DELETE | 删除从服务器上该资源 |
按照这个规则,你能够发送一条要求删除指定博文的请求,如:
DELETE /blog/15 HTTP/1.1
注释:实际上,HTTP协议里一共定义了9种HTTP方法,但它们中的大部分并无获得普遍的使用和支持。实际上,许多现代的浏览器并不支持PUT和DELETE方法
除了第一行,HTTP请求所包含其余行的信息被称为HTTP请求头,头信息还包含:主机、客户端接受响应的格式、客户端所用代理的应用程序等。还有许多其它的HTTP请求头存在,你能够在维基百科的 List of HTTP header fields 中找到它们。
服务端获得请求,它就明确地知道客户端须要哪一个资源(经过URI)以及但愿对该资源进行什么操做(经过HTTP方法)。例如,对于一个GET请求,服务端将准备资源,并在HTTP响应中将其返回给客户端。如,xkcd服务端返回的响应:
按照HTTP协议的格式,被返回给客户端的响应以下所示:
HTTP/1.1 200 OK Date: Sat, 02 Apr 2011 21:05:05 GMT Server: lighttpd/1.4.19 Content-Type: text/html <html> <!-- HTML for the xkcd comic --> </html>
HTTP响应包含了客户端所请求的资源(在这个例子里是HTML),以及与响应相关的信息。与请求头相似,第一行也最重要,它给出的是HTTP状态码(在 上面的例子里是200)。状态码报告了响应的状态,如,请求是否成功?是否存在错误?不一样的状态码表示着成功、错误或者通知客户端须要作其它一些事(如重 定向到另外一页)。完整的列表能够在维基百科的 HTTP状态代码列表 中找到。
全部这些响应信息,组成了响应头。其中一个重要的HTTP响应头消息被称为Content-Type。服务器上的每一个资源均可以以不一样的格式返回给客户端,如HTML、XML或JSON等;经过在Content-Type里设置如text/html这样的互联网媒体类型码,能够告知客户端,服务器给出的响应格式是什么。常见的媒体类型能够在维基百科的互联网媒体类型列表 里找到。
还存在不少其余的HTTP响应头,其中有些能够起到很重要的做用。好比,某些响应头能够用来维护HTTP缓存。
“请求-响应”对话是驱动Web上全部通讯的基础,它是如此的强大和重要,它又是如此的简单。
最重要的事实是,无论你使用哪一种开发语言,构建哪一种应用(Web、手机、JSON应用程序接口等),遵循哪一种开发理论,应用程序的最终目标老是一致的:理解每一个请求,建立并返回相应的响应。
Symfony2就是来完成这一“使命”的:
要更了解HTTP协议规范,能够参考 HTTP 1.1 RFC 或者 HTTP Bis (用更直白明了方式的来讲明HTTP协议规范)。另外,有一款叫作 Live HTTP Headers 的Firefox浏览器扩展能够用来查看上网过程当中请求、响应头的内容。
那么,怎么用PHP来获知“请求”,并建立“响应”呢?PHP对实际的操做进行了封装,你要作的,相对还算简单:
<?php $uri = $_SERVER['REQUEST_URI']; $foo = $_GET['foo']; header('Content-type: text/html'); echo 'The URI requested is: '.$uri; echo 'The value of the "foo" parameter is: '.$foo;
虽然看上去有点奇怪,但这一小段代码能够从HTTP请求头里提取信息,并依据这些信息建立了响应内容。你并不须要本身写代码来解析HTML消息格式,由于PHP为你准备了一系列的全局变量,如:$_SERVER和$_GET,它们包含了关于请求的全部信息。你还能够经过调用header()函数来指定响应头信息;或者用echo一类的语句直接输出响应里的正文内容。PHP会负责把你指定的全部信息组成一个有效的HTTP响应,返回给客户端(注意,中文会通过编码传输)。
HTTP/1.1 200 OK Date: Sat, 03 Apr 2011 02:14:33 GMT Server: Apache/2.2.17 (Unix) Content-Type: text/html The URI requested is: /testing?foo=symfony The value of the "foo" parameter is: symfony
Symfony2使用两个类能够很是容易地与请求和响应交互,从而取代原始的PHP方式。Request类是HTTP请求面向对象的简单表示。有了它,你获取请求信息将易如反掌。
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 use Symfony\Component\HttpFoundation\Request; $request = Request::createFromGlobals(); // 请求的URI (如:/about) ,没有任何查询参数 $request->getPathInfo(); // 分别检索GET和POST变量 $request->query->get('foo'); $request->request->get('bar'); // 检索被foo标识的UploadedFile实例 $request->files->get('foo'); $request->getMethod(); // GET, POST, PUT, DELETE, HEAD $request->getLanguages(); // 客户端接受语言的数组 use Symfony\Component\HttpFoundation\Request; $request = Request::createFromGlobals(); // 请求的URI (如:/about) ,没有任何查询参数 $request->getPathInfo(); // 分别检索GET和POST变量 $request->query->get('foo'); $request->request->get('bar', 'default value if bar does not exist'); // 检索服务器变量 $request->server->get('HTTP_HOST'); // 检索上传文件参数 $request->files->get('foo'); // 检索cookie的值 $request->cookies->get('PHPSESSID'); // 检索一个http头是否是规范化 $request->headers->get('host'); $request->headers->get('content_type'); $request->getMethod(); // GET, POST, PUT, DELETE, HEAD $request->getLanguages(); // 一个获取语言数组的方法
Request类在后台所作的大量工做能使你省很多心。如isSecure()方法经过用PHP检查三个不一样的值来肯定用户是否使用了安全连接(经过https)。
ParameterBags 和 Request 类的成员
如上,$_GET 和 $_POST 里的值能够经过公有成员query和request来访问。每个都是 Symfony\Component\HttpFoundation\ParameterBag 类的对象,拥有如下方法: get(), has(), all() 等等。 事实上,上面例子里提到的公有成员都是ParameterBag的实例。
Request类还有一个公有的 attributes 成员,里面包含了PHP框架的一些运行数据。Symfony2框架在这个变量里保存了当前请求所匹配的URL路由,好比_controller,id(若是你使用了 {id} 通配符),甚至当前路由的名称(_route)。attributes成员实际就是用来保存和提供与当前请求相关的运行环境信息。
Symfony2还提供了一个Response类,一个HTTP响应的简单PHP表示。这容许你使用面向对象的接口去构建返回客户端所需的响应。
use Symfony\Component\HttpFoundation\Response; $response = new Response(); $response->setContent('<html><body><h1>Hello world!</h1></body></html>'); $response->setStatusCode(Response::HTTP_OK); $response->headers->set('Content-Type', 'text/html'); // prints the HTTP headers followed by the content $response->send();
symfony新的2.4版:已经支持了引入HTTP状态代码
就算Symfony2再没提供其它工具,你也已经有了能够轻易访问请求信息的工具包和用来建立响应的面向对象接口。即便你学了更多Symfony2的功能,也请牢记,你应用程序的目标始终是解释请求,并根据你应用程序的逻辑建立相应的响应。
Request类和Response类都是Symfony2中名为HttpFoundation组件的一部分。该组件能够独立使用,它还提供处理会话和文件上传的类。
同HTTP同样,Request和Response对象也很简单。应用程序最复杂的部分是在二者之间写些什么。换句话说,真正的工做来自于编写解释请求并建立响应的代码。
你的应用程序可能作了诸如发送电子邮件、处理提交表单、向数据库写入数据、渲染HTML页面和确保内容安全性等诸多事情,但你如何来管理这一切,同时还要保持你代码的组织性和可维护性呢?
Symfony2就是用来解决上述问题,而无须让你所以分心。
前端控制器
传统方式中构建的应用程序,网站中的每一“页”都是它自身的物理文件。
index.php contact.php blog.php
使用这种方式存在几个问题:不灵活的URL(你是否能够将blog.php文件更名为news.php,而无须破坏你全部的连接?)、每一个文件都必须手工包含一些核心文件集以确保安全性(数据库链接和网站外观必须保持一致)。
更好的解决方案是使用前端控制器:单一的PHP文件,该文件用来处理进入应用程序的全部请求。例如:
/index.php | 执行index.php |
/index.php/contact | 执行index.php |
/index.php/blog | 执行index.php |
使用Apache的mod_rewrite模块(或其它Web服务器的类似模块),URL能够很方便地被清理成诸如:/、/contact、/blog 这样的连接。
如今,全部请求的处理都彻底同样。前端控制器将被始终执行,不一样的URL将被内部路由到你应用程序的不一样部分,而无须根据不一样的URL执行不一样的PHP文件。这样就解决了前面传统方式所带来的问题。几乎全部现代应用程序均可以作到这一点,其中包括相似WordPress这样的应用程序。
保持代码的组织性
前端控制器又是如何知道哪一个页面要被渲染,如何正确渲染呢?这须要判断传入的URI,针对性地调用不一样的代码。这也不是容易的差事:
// index.php use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; $request = Request::createFromGlobals(); $path = $request->getPathInfo(); // the URI path being requested if (in_array($path, array('', '/'))) { $response = new Response('Welcome to the homepage.'); } elseif ($path == '/contact') { $response = new Response('Contact us'); } else { $response = new Response('Page not found.', Response::HTTP_NOT_FOUND); } $response->send();
幸运的是,这正是Symfony2被设计来解决的问题之一。
让Symfony2来处理请求,开发工做就会变得简单不少。Symfony2在每次处理,都会遵循下面的模式:
传入的请求经路由,会由具体的控制器函数进行处理,并返回Response对象。
你网站的每一页都被定义在路由配置文件中,在那里不一样的URL被映射到不一样的PHP函数。每一个PHP函数(又名 controller)的工做就是获得请求的信息(也可使用Symfony2中有许多其它的工具)去建立并返回一个Response对象。
就是这么简单,让咱们回顾一下:
一、每一个请求执行前端控制器文件;
二、根据你的路由配置和请求信息,路由系统决定应该执行哪一个PHP函数;
三、正确的PHP函数被执行,在那里你的代码将建立并返回相应的Response对象。
先不考虑太多的细节,举一个请求处理实例。假设你要在Symfony2应用里增长一个/contact页面。首先,修改路由配置文件:
contact: pattern: /contact defaults: { _controller: AcmeDemoBundle:Main:contact }
这个例子使用 YAML来定义路由的配置,你也能够用XML或PHP来写。
当有人访问/contact页时,该路由条目被匹配,同时执行指定的控制器。
你在 routing chapter 里将会了解到,AcmeDemoBundle:Main:contact是简写法,指向的是MainController类里的contactAction方法函数。
class MainController { public function contactAction() { return new Response('<h1>联系咱们!</h1>'); } }
这个控制器很是简单,仅仅建立了一个内容为HTML“<h1>联系咱们!</h1>”的Response。参考controller chapter你能够了解到控制器如何渲染模板,从而使你的“表现层”代码能够被写在单独的模板文件里。控制器不须要考虑一些复杂的工做,如:读写数据库,处理由用户提交的数据,发送电子邮件等。
如今你知道任何应用的目的都是处理传入的请求,建立相应的响应。当应用程序的规模逐渐增加,要保持代码的结构和易维护性就变得愈来愈困难。毕竟,有不少事情是你不得不反复作的:写数据库,渲染和重用模板,处理表单提交,发送电子邮件,验证用户的输入和保证安全性。
好消息是,这些事情都不是发射神舟飞船,并不特殊。Symfony2提供了你构建应用所需的几乎所有工具,因此你能够专心于创造应用,而不是“从新发明轮子”。Symfony2还有一点值得表扬,就是你能够选择是使用整个框架,仍是只使用它部分的功能。
那Symfony2到底是什么?首先,Symfony2是一个由20多个独立的开发库组成的工具集,你能够在任何PHP项目里使用这些代码。这些开发库,被称做Symfony2组件,功能涵盖了绝大部分的开发需求。举一些例子:
每个组件都是独立的,可用于任何PHP项目中,而无论你是否使用了Symfony2框架。它们的每个既能够在须要时使用,也能够在必要时被替换。
那么,什么是Symfony2框架呢?Symfony2框架是个PHP库,它实现两个功能:
这个框架的目标是整合许多独立的工具,以期给开发人员一致的体验。甚至就连Symfony2框架自己也是一个Bundle(相似插件),在必要时也能够被从新配置甚至替换掉。
Symfony2为快速开发应用程序提供了强大的工具集,普通用户能够经过Symfony2的发行版(缺省提供了合理的项目架构)迅速上手,对于更高级的用户而言,只有想不到,没有作不到(The sky is the limit.)。