恭喜你!通过学习Symfony2,你将用你自己的方式开发出更加高效、全面和流行的Web应用(当然,要受到用人单位或同行的欢迎,还是得靠你自己)。Symfony2的存在是为了要解决最根本的问题:即提供一个开发工具,使开发者能以自己的方式更快速地开发出更为健壮的应用程序。Symfony2集成了许多技术的优点,包括工具和概念,你将学到大多数人多年来努力的方向。换句话说,你不只是在学习Symfony2,你还将学习Web基础原理、最佳开发实践以及如何使用许多新的、优秀的PHP开发库。所以,请做好准备!

本章将从解释Web开发过程中最常接触的基础概念开始:HTTP协议。无论技术背景或首选编程语言是什么,本章的内容对于所有人来说都是必须要了解的。

HTTP很简单

HTTP(超文本传输协议)是一个允许两个机器相互通信的文本语言。举例来说,当你要去 xkcd网站查看最新的漫画时,下列会话(近似地)将在你的浏览器和服务器之间发生:

虽然实际使用的语言将更加正规,但它依然是很简单的。HTTP定义了这种简单文本语言的语义和语法。而无论你从事何种的Web开发,你的服务器总是要理解基于文本的请求,并返回基于文本的响应。

Symfony2是基于现实构建的,无论你是否意识到这一点,HTTP都是你每天所需的。随着对Symfony2学习的深入,你将学会如何掌握它。

第一步:客户端发送一个请求

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/ 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  OK
Date: Sat, Apr :: GMT
Server: lighttpd/1.4.
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上所有通信的基础,它是如此的强大和重要,它又是如此的简单。

最重要的事实是,不管你使用哪种开发语言,构建哪种应用(Web、手机、JSON应用程序接口等),遵循哪种开发理论,应用程序的最终目标总是一致的:理解每个请求,创建并返回相应的响应。

Symfony2就是来完成这一“使命”的:

要更了解HTTP协议规范,可以参考 HTTP 1.1 RFC 或者 HTTP Bis (用更直白明了方式的来说明HTTP协议规范)。另外,有一款叫做 Live HTTP Headers 的Firefox浏览器扩展可以用来查看上网过程中请求、响应头的内容。

PHP是如何处理请求和返回响应的

那么,怎么用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中的请求和响应

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来处理请求,开发工作就会变得简单很多。Symfony2在每次处理,都会遵循下面的模式:

传入的请求经路由,会由具体的控制器函数进行处理,并返回Response对象。

你网站的每一页都被定义在路由配置文件中,在那里不同的URL被映射到不同的PHP函数。每个PHP函数(又名 controller)的工作就是得到请求的信息(也可以使用Symfony2中有许多其它的工具)去创建并返回一个Response对象。

就是这么简单,让我们回顾一下:

1、每个请求执行前端控制器文件;
2、根据你的路由配置和请求信息,路由系统决定应该执行哪个PHP函数;
3、正确的PHP函数被执行,在那里你的代码将创建并返回相应的Response对象。

Symfony2处理请求的实例

先不考虑太多的细节,举一个请求处理实例。假设你要在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的组件

那Symfony2到底是什么?首先,Symfony2是一个由20多个独立的开发库组成的工具集,你可以在任何PHP项目里使用这些代码。这些开发库,被称作Symfony2组件,功能涵盖了绝大部分的开发需求。举一些例子:

  • HttpFoundation – 包含Request和 Response相关的类,以及处理会话和文件上传的类;
  • Routing – 强大、快速的URL路由系统,你可以指定对于特定的URI(如:/contact),请求该如何处理(如:执行contactAction()方法);
  • Form – 一个灵活的、全功能的创建表单和处理表单提交的框架;
  • Validator - 创建数据规则,并可以验证数据(不仅是用户提交的数据)是否符合所创规则的系统;
  • ClassLoader – 类的自动加载器,无需在使用PHP类时写require来包含对应的源文件;
  • Templating – 一个渲染模板、处理模板继承关系(即模板嵌套)和执行其他通用模板任务的工具包;
  • Security – 一个功能强大的,能处理应用程序内所有安全任务的库;
  • Translation – 一个用来翻译应用程序内字符串的框架。

每一个组件都是独立的,可用于任何PHP项目中,而不管你是否使用了Symfony2框架。它们的每一个既可以在需要时使用,也可以在必要时被替换。

完整的解决方案:Symfony2框架

那么,什么Symfony2框架呢?Symfony2框架是个PHP库,它实现两个功能:

  1. 提供经选择的组件(如:Symfony2组件)和第三方库(如:用Swiftmailer发送电子邮件);
  2. 提供合理的配置以及将这一切都粘合起来的“胶水”库。

这个框架的目标是整合许多独立的工具,以期给开发人员一致的体验。甚至就连Symfony2框架本身也是一个Bundle(类似插件),在必要时也可以被重新配置甚至替换掉。

Symfony2为快速开发应用程序提供了强大的工具集,普通用户可以通过Symfony2的发行版(缺省提供了合理的项目架构)迅速上手,对于更高级的用户而言,只有想不到,没有做不到(The sky is the limit.)。

第一章:Symfony2和HTTP基本原理的更多相关文章

  1. (转)iOS Wow体验 - 第一章 - iOS人机界面设计规范纵览

    本文是<iOS Wow Factor:Apps and UX Design Techniques for iPhone and iPad>第一章译文精选,其余章节将陆续放出. 关于本套译文 ...

  2. 漫谈格兰杰因果关系(Granger Causality)——第一章 野火烧不尽,春风吹又生

    2017年7月9日上午6点10分,先师胡三清同志--新因果关系的提出者.植入式脑部电极癫痫治疗法的提出者.IEEE高级会员,因肺癌医治无效于杭州肿瘤医院去世,享年50岁.余蒙先师厚恩数载,一朝忽闻先师 ...

  3. Intel汇编语言程序设计学习-第一章 基本概念

    第一章基本概念 1.1  简单介绍 本书着重讲述MS-Windows平台上IA-32(Intel Architecture 32bit,英特尔32位体系架构)兼容微处理器的汇编语言程序设计,可以使用I ...

  4. 《Django By Example》第一章 中文 翻译 (个人学习,渣翻)

    书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者注:本人目前在杭州某家互联网公司工作, ...

  5. MyBatis3.2从入门到精通第一章

    第一章一.引言mybatis是一个持久层框架,是apache下的顶级项目.mybatis托管到goolecode下,再后来托管到github下.(百度百科有解释)二.概述mybatis让程序将主要精力 ...

  6. Nova PhoneGap框架 第一章 前言

    Nova PhoneGap Framework诞生于2012年11月,从第一个版本的发布到现在,这个框架经历了多个项目的考验.一直以来我们也持续更新这个框架,使其不断完善.到现在,这个框架已比较稳定了 ...

  7. 第一章 MYSQL的架构和历史

    在读第一章的过程中,整理出来了一些重要的概念. 锁粒度  表锁(服务器实现,忽略存储引擎). 行锁(存储引擎实现,服务器没有实现). 事务的ACID概念 原子性(要么全部成功,要么全部回滚). 一致性 ...

  8. 第一章 Java多线程技能

    1.初步了解"进程"."线程"."多线程" 说到多线程,大多都会联系到"进程"和"线程".那么这两者 ...

  9. 【读书笔记】《编程珠玑》第一章之位向量&位图

    此书的叙述模式是借由一个具体问题来引出的一系列算法,数据结构等等方面的技巧性策略.共分三篇,基础,性能,应用.每篇涵盖数章,章内案例都非常切实棘手,解说也生动有趣. 自个呢也是头一次接触编程技巧类的书 ...

  10. 《JavaScript高级程序设计(第3版)》阅读总结记录第一章之JavaScript简介

    前言: 为什么会想到把<JavaScript 高级程序设计(第 3 版)>总结记录呢,之前写过一篇博客,研究的轮播效果,后来又去看了<JavaScript 高级程序设计(第3版)&g ...

随机推荐

  1. 数据库知识整理<六>

    聚合函数与分组 6.1使用聚合函数进行数据统计: 聚合函数常见的有以下几种: count:返回该结果集中行的数目. sum:返回结果集中所有值的总和. avg:返回结果集中所有值的平均值. max:返 ...

  2. php乱码

    1:php 编码是utf-8 但是接口需要是gbk 这么办?? $message = "你的微点管理地址为:".$shortUrl." [请保存信息]"; // ...

  3. Beetl 1.25 发布,java模板引擎

    Beetl 1.25 发布改进记录包括: Beetl支持同JS一样三元逻辑表达式,如:    var c = a>1?’li’;’miao’;    var d = b>1?:’ok’; ...

  4. C#设计模式(4)——抽象工厂模式

    一.引言 在上一专题中介绍了工厂方法模式,工厂方法模式是为了克服简单工厂模式的缺点而设计出来的,简单工厂模式的工厂类随着产品类的增加需要增加额外的代码),而工厂方法模式每个具体工厂类只完成单个实例的创 ...

  5. 微软BI 之SSIS 系列 - ETL 转换时关于 Code Page (1252 and 936) 转换错误的原因和解决方法

    开篇介绍 最近经常碰到在 ETL 练习中出现这种转换失败的问题,试了多种方式,同样的代码同样的源结构和表结构但是一直不能成功执行,包报错.一般有这么几种错误: Error at DST_LOAD_DA ...

  6. 调研一类软件的发展演变—聊天软件( 1000-2000 words, in Chinese)

    因为本人平时对聊天软件的涉及比周边其他同学而言所涉及的是比较多的.所以说想写写这个东西.(ps本文里面的具体通讯信息的时间安排不分先后) 也许最起初的通讯信息的传达是利用.烽火狼烟这一类可以远距离视觉 ...

  7. [C++] socket - 1 [简单TCP通信C\S代码]

    服务端: #include<iostream> #include<winsock2.h> #include<stdio.h> #pragma comment(lib ...

  8. [游戏模版16] Win32 飞机射击 敌人追踪

    >_<:AI introduction. >_<:According the plane position (nowX,nowY) relative to birds' pos ...

  9. ASP.NET 5系列教程 (三):view components介绍

    在ASP.NET MVC 6中,view components (VCs) 功能类似于虚拟视图,但是功能更加强大. VCs兼顾了视图和控制器的优点,你可以把VCs 看作一个Mini 控制器.它负责控制 ...

  10. 浅谈sql中的in与not in,exists与not exists的区别

    转 浅谈sql中的in与not in,exists与not exists的区别   12月12日北京OSC源创会 —— 开源技术的年终盛典 »   sql exists in 1.in和exists ...