<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>4's symfony blog &#187; 跳转</title>
	<atom:link href="http://www.foolbirds.com/t/%e8%b7%b3%e8%bd%ac/feed" rel="self" type="application/rss+xml" />
	<link>http://www.foolbirds.com</link>
	<description>all about symfony</description>
	<lastBuildDate>Fri, 14 Oct 2011 12:36:02 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>跳并快乐着－symfony跳转指南</title>
		<link>http://www.foolbirds.com/redirect-and-forward-in-symfony.html</link>
		<comments>http://www.foolbirds.com/redirect-and-forward-in-symfony.html#comments</comments>
		<pubDate>Tue, 17 Mar 2009 04:24:39 +0000</pubDate>
		<dc:creator>maker</dc:creator>
				<category><![CDATA[symfony]]></category>
		<category><![CDATA[forward]]></category>
		<category><![CDATA[redirect]]></category>
		<category><![CDATA[跳转]]></category>

		<guid isPermaLink="false">http://www.foolbirds.com/?p=649</guid>
		<description><![CDATA[项目接近尾声，闲来无事写一点东西活跃活跃气氛。在日常的web开发中，跳转是一个很常见的操作，成功了要跳转，错误了要跳转，满足某某条件也要跳转，symfony作为一款成熟的开发框架对跳转的处理也是非常多样的。
一. 关于跳转
虽说多样，但万变不离其宗，一般的跳转分为两种，forward（转发）和redirect（重定向），两种方法虽然目的都是为了进行跳转但是本质上还是有很大差别的。
所谓forward，是一个action将当前的请求交给另外一个action处理，这个过程是在同一个http请求中完成的，整个过程不涉及客户端，url地址也不会发生改变。
示例1
public function executeActionA($request)
{
// 一些处理
// to ActionB: 剩下的就交给你了
$this-&#62;forward('default', 'actionb');
}
public function executeActionB($request)
{
// to ActionA: 交给我你就放心吧
// 又一些处理
}
示例一中，ActionA将处理工作交给的ActionB，其实其效果是和下例一样的。
示例2
public function executeActionC($request)
{
// 一些处理
// 又一些处理
// ps : 我是全能，ActionA和ActionB能做的我自己就能做
}
上面这两个例子就如同我们雇佣一个程序员一个美工或者雇佣一个懂美工的程序员一样，我们将事件处理过程分开总是有各种各样的原因，比如为了逻辑清晰，代码重用等等等等，所以在很多情况下我们就需要使用forward。
说完forward我们再来说redirect，其实我觉得redirect才能够叫做真正的跳转，很多时候我觉得forward就象调用函数。一个真正的redirect涉及了两次http请求，浏览器发送了一个http请求之后，服务端根据业务需要进行跳转，这样服务端会向浏览器返回一个跳转信息，这个跳转信息可能是一个重定向的http header，也可能是一段带有跳转代码的html或者javascript，浏览器接到请求根据跳转信息进行第二次http 请求，这个第二次请求不同于forward的第二个Action，这个请求可以在程序内，也可以在程序外，比如说跳到google, 而用forward就象蹲监狱，再怎么跳也就是换换牢房，想出去是不可能了，除非你是Michael Scofield。
示例3
public function executeActionA($request)
{
// 我要换牢房
$this-&#62;redirect('fox/room');
}
public function executeActionB($request)
{
// 我要换去Sucre的牢房拆马桶
$this-&#62;redirect("fox/room?user='Fernando Sucre'");
}
public function executeActionC($request)
{
// 和哥哥越狱到谷歌去
$this-&#62;redirect('http://g.cn/?with_my_brother=true');
}
这里扯的有点远，其实我觉得在看我文章的朋友其实已经有一定的symfony基础的，所以不需要细细的去讲，只要给大家一些提示就可以。forward和redirect还有很关键的一点区别，就是forward进行转发之后原来的请求参数不会变，这里的请求参数指post, get, cookie什么什么什么的， 而redirect就需要你通过url将你需要的参数再传过去， symfony中貌似有http_build_query()这么一个函数.
示例4
public function executeActionA($request)
{
// 所有和我从Fox River跑出来的朋友一起去巴拿马
$this-&#62;redirect('panama.com?'.http_build_query($request-&#62;getPostParameters()));
}
二. symfony中的跳转
关于forward和redirect就介绍到这里，下面来介绍symfony中的跳转方法。
function forward($module, $action)
最基本的转发动作，参数是模块名和动作名。
示例5，新建立模块的Index方法都是这样的。
public function executeIndex(sfWebRequest $request)
{
// 将默认动作转发到默认模块
$this-&#62;forward('default', 'index');
}

function forward404($message = null)
forward404动作其实和throw [...]]]></description>
			<content:encoded><![CDATA[<p>项目接近尾声，闲来无事写一点东西活跃活跃气氛。在日常的web开发中，跳转是一个很常见的操作，成功了要跳转，错误了要跳转，满足某某条件也要跳转，symfony作为一款成熟的开发框架对跳转的处理也是非常多样的。</p>
<p><strong>一. 关于跳转</strong></p>
<p style="padding-left: 30px;">虽说多样，但万变不离其宗，一般的跳转分为两种，forward（转发）和redirect（重定向），两种方法虽然目的都是为了进行跳转但是本质上还是有很大差别的。</p>
<p style="padding-left: 30px;">所谓forward，是一个action将当前的请求交给另外一个action处理，这个过程是在同一个http请求中完成的，整个过程不涉及客户端，url地址也不会发生改变。</p>
<p style="padding-left: 30px;">示例1</p>
<p style="padding-left: 30px;"><code>public function executeActionA($request)<br />
{<br />
// 一些处理<br />
// to ActionB: 剩下的就交给你了<br />
$this-&gt;forward('default', 'actionb');<br />
}<br />
public function executeActionB($request)<br />
{<br />
// to ActionA: 交给我你就放心吧<br />
// 又一些处理<br />
}</code></p>
<p style="padding-left: 30px;">示例一中，ActionA将处理工作交给的ActionB，其实其效果是和下例一样的。</p>
<p style="padding-left: 30px;">示例2</p>
<p style="padding-left: 30px;"><code>public function executeActionC($request)<br />
{<br />
// 一些处理<br />
// 又一些处理<br />
// ps : 我是全能，ActionA和ActionB能做的我自己就能做<br />
}</code></p>
<p style="padding-left: 30px;">上面这两个例子就如同我们雇佣一个程序员一个美工或者雇佣一个懂美工的程序员一样，我们将事件处理过程分开总是有各种各样的原因，比如为了逻辑清晰，代码重用等等等等，所以在很多情况下我们就需要使用forward。</p>
<p style="padding-left: 30px;">说完forward我们再来说redirect，其实我觉得redirect才能够叫做真正的跳转，很多时候我觉得forward就象调用函数。一个真正的redirect涉及了两次http请求，浏览器发送了一个http请求之后，服务端根据业务需要进行跳转，这样服务端会向浏览器返回一个跳转信息，这个跳转信息可能是一个重定向的http header，也可能是一段带有跳转代码的html或者javascript，浏览器接到请求根据跳转信息进行第二次http 请求，这个第二次请求不同于forward的第二个Action，这个请求可以在程序内，也可以在程序外，比如说跳到google, 而用forward就象蹲监狱，再怎么跳也就是换换牢房，想出去是不可能了，除非你是Michael Scofield。</p>
<p style="padding-left: 30px;">示例3</p>
<p style="padding-left: 30px;"><code>public function executeActionA($request)<br />
{<br />
// 我要换牢房<br />
$this-&gt;redirect('fox/room');<br />
}<br />
public function executeActionB($request)<br />
{<br />
// 我要换去Sucre的牢房拆马桶<br />
$this-&gt;redirect("fox/room?user='Fernando Sucre'");<br />
}<br />
public function executeActionC($request)<br />
{<br />
// 和哥哥越狱到谷歌去<br />
$this-&gt;redirect('http://g.cn/?with_my_brother=true');<br />
}</code></p>
<p style="padding-left: 30px;">这里扯的有点远，其实我觉得在看我文章的朋友其实已经有一定的symfony基础的，所以不需要细细的去讲，只要给大家一些提示就可以。forward和redirect还有很关键的一点区别，就是forward进行转发之后原来的请求参数不会变，这里的请求参数指post, get, cookie什么什么什么的， 而redirect就需要你通过url将你需要的参数再传过去， symfony中貌似有http_build_query()这么一个函数.</p>
<p style="padding-left: 30px;">示例4</p>
<p style="padding-left: 30px;"><code>public function executeActionA($request)<br />
{<br />
// 所有和我从Fox River跑出来的朋友一起去巴拿马<br />
$this-&gt;redirect('panama.com?'.http_build_query($request-&gt;getPostParameters()));<br />
}</code></p>
<p><strong>二. symfony中的跳转</strong></p>
<p style="padding-left: 30px;">关于forward和redirect就介绍到这里，下面来介绍symfony中的跳转方法。</p>
<p style="padding-left: 30px;"><strong>function <span style="color: #ff0000;">forward</span>($module, $action)</strong></p>
<p style="padding-left: 60px;">最基本的转发动作，参数是模块名和动作名。</p>
<p style="padding-left: 60px;">示例5，新建立模块的Index方法都是这样的。</p>
<p style="padding-left: 60px;"><code>public function executeIndex(sfWebRequest $request)<br />
{<br />
// 将默认动作转发到默认模块<br />
$this-&gt;forward('default', 'index');<br />
}</code></p>
<p style="padding-left: 60px;">
<p style="padding-left: 30px;"><strong>function <span style="color: #ff0000;">forward404</span>($message = null)</strong></p>
<p style="padding-left: 60px;">forward404动作其实和throw new sfError404Exception的效果是一样的， 在symfony中可以通过设置404动作来控制404的输出，这样实际上就是一个转发到404错误处理动作的跳转， 返回404异常在程序中是很常见的，比如参数错误，数据错误等等等等等等，我们都可以直接抛出404异常。</p>
<p style="padding-left: 60px;">示例6</p>
<p style="padding-left: 60px;"><code>public function executeActionA($request)<br />
{<br />
$id = (int) $request-&gt;getParameter('id');<br />
if ($id &lt; 1) {<br />
$this-&gt;forward404();<br />
}<br />
$product = ProductPeer::retrieveByPk($id);<br />
if (!is_object($product)) {<br />
$this-&gt;forward404();<br />
}<br />
//我们将对象注册到模板中去，其实和$this-&gt;product=$product是一样的<br />
$this-&gt;setVar('product', $product);<br />
}</code></p>
<p style="padding-left: 30px;"><strong>function <span style="color: #ff0000;">forwardIf</span>($condition, $module, $action)</strong></p>
<p style="padding-left: 60px;">当$condition为&#8221;真&#8221;的时候转发到$module/$action</p>
<p style="padding-left: 60px;">示例7</p>
<p style="padding-left: 60px;"><code>public function executeCreate($request)<br />
{<br />
$product = new Product;<br />
$product-&gt;setName('产品1');<br />
// 创建产品，成功则跳转到列表，创建失败则抛出404<br />
$this-&gt;forwardIf($product, 'product', 'list');<br />
$this-&gt;forward404();<br />
}</code></p>
<p style="padding-left: 30px;"><strong>function <span style="color: #ff0000;">forwardUnless</span>($condition, $module, $action)</strong></p>
<p style="padding-left: 60px;">当$condition为&#8221;假&#8221;的时候转发到$module/$action</p>
<p style="padding-left: 60px;">示例8</p>
<p style="padding-left: 60px;"><code>public function  executeAction($request)<br />
{<br />
$product = ProductPeer::retrieveByPk($this-&gt;getParameter('id'));<br />
$this-&gt;forward($product, 'default', 'error404');<br />
}</code></p>
<p style="padding-left: 30px;"><strong>function <span style="color: #ff0000;">forward404If</span>($condition, $message = null)</strong></p>
<p style="padding-left: 60px;">当$condition为“真“的时候抛出404异常</p>
<p style="padding-left: 60px;">示例9</p>
<p style="padding-left: 60px;"><code>public function executeShow($request)<br />
{<br />
$id = intval($request-&gt;getParameter('id'));<br />
// 如果id小于0抛出异常<br />
$this-&gt;forward404If($id&lt;0, 'parameter error');<br />
$product = ProductPeer::retrieveByPk($id);<br />
// 如果产品不存在抛出异常<br />
$this-&gt;forward404If(!$product, 'product not exists');<br />
$this-&gt;object = $product;<br />
}</code></p>
<p style="padding-left: 30px;"><strong>function <span style="color: #ff0000;">forward404Unless</span>($condition, $message = null)</strong></p>
<p style="padding-left: 60px;">当$condition为“假“的时候抛出404异常, 实际应用中这个方法比forward404If更方便</p>
<p style="padding-left: 60px;">示例10</p>
<p style="padding-left: 60px;"><code>public function executeShow($request)<br />
{<br />
$id = intval($request-&gt;getParameter('id'));<br />
// 如果id小于0抛出异常<br />
$this-&gt;forward404If($id&lt;0, 'parameter error');<br />
$product = ProductPeer::retrieveByPk($id);<br />
// 如果产品不存在抛出异常<br />
$this-&gt;forward404Unless($product, 'product not exists');<br />
$this-&gt;object = $product;<br />
}</code></p>
<p style="padding-left: 30px;"><strong>function <span style="color: #ff0000;">redirect</span>($url, $statusCode = 302)</strong></p>
<p style="padding-left: 60px;">跳转到$url，返回http状态码，$url可以是内部url也可以是外部url.</p>
<p style="padding-left: 60px;">示例11</p>
<p style="padding-left: 60px;"><code>public function executeActionA($request)<br />
{<br />
$this-&gt;redirect('g.cn');<br />
}<br />
public function executeActionB($request)<br />
{<br />
$this-&gt;redirect('default/index?action=b');<br />
}</code></p>
<p style="padding-left: 30px;"><strong>function <span style="color: #ff0000;">redirect404</span>()</strong></p>
<p style="padding-left: 60px;">跳转到404动作，404处理动作可以通过settings.yml进行设置, 这个动作是不用给参数的，symfony会自动调用系统设置。</p>
<p style="padding-left: 30px;"><strong>function <span style="color: #ff0000;">redirectIf</span>($condition, $url, $statusCode = 302)</strong></p>
<p style="padding-left: 60px;">如果$condition为“真”则跳转到$url</p>
<p style="padding-left: 60px;">示例12</p>
<p style="padding-left: 60px;"><code>public function executeCreate($request)<br />
{<br />
$product = new Product;<br />
$product-&gt;setName('产品2');<br />
//创建成功进入编辑页面<br />
$this-&gt;redirectIf($product-&gt;save(), 'product/update?id='.$product-&gt;getId());<br />
//创建失败加载Error模板<br />
return sfView::ERROR;<br />
}</code></p>
<p style="padding-left: 30px;"><strong>function <span style="color: #ff0000;">redirectUnless</span>($condition, $url, $statusCode = 302)</strong></p>
<p style="padding-left: 60px;">如果$condition为“假”则跳转到$url, 参考forwardUnless</p>
<p><strong>三. 结束语</strong></p>
<p style="padding-left: 30px;">本文旨在抛砖引玉，其实关于跳转还有很多的技巧，这个就要在实际应用中慢慢积累了。</p>
<ul class="related_post"><li><a href="http://www.foolbirds.com/use_symfony_filter_to_filteredurl.html" title="使用symfony filter 过滤URL">使用symfony filter 过滤URL</a></li><li><a href="http://www.foolbirds.com/%e4%bb%bfsymfony%e6%9c%ba%e5%88%b6%e5%ae%9e%e7%8e%b0%e4%b8%8d%e7%94%a8require%e6%88%96%e8%80%85include%e6%9d%a5%e5%ae%9e%e4%be%8b%e5%8c%96%e7%b1%bb.html" title="仿symfony机制实现不用require或者include来实例化类">仿symfony机制实现不用require或者include来实例化类</a></li><li><a href="http://www.foolbirds.com/use-datetime-in-php5-1-x-with-symfony.html" title="symfony1.4 DateTime对于PHP低版本的兼容问题">symfony1.4 DateTime对于PHP低版本的兼容问题</a></li><li><a href="http://www.foolbirds.com/%e5%a6%82%e4%bd%95%e5%9c%a8fixtures-yml%e5%86%99%e5%be%aa%e7%8e%af%e6%b7%bb%e5%8a%a0%e6%95%b0%e6%8d%ae.html" title="如何在fixtures.yml写循环添加数据">如何在fixtures.yml写循环添加数据</a></li><li><a href="http://www.foolbirds.com/symfony-1-4-database-utf8.html" title="symfony 1.4 数据库 utf8设置">symfony 1.4 数据库 utf8设置</a></li><li><a href="http://www.foolbirds.com/symfony-cheat-sheet.html" title="symfony cheat sheet">symfony cheat sheet</a></li><li><a href="http://www.foolbirds.com/cheat-sheets.html" title="Cheat Sheets!">Cheat Sheets!</a></li><li><a href="http://www.foolbirds.com/how-to-use-swift-to-send-mail-in-symfon.html" title="如何使用swift发送邮件">如何使用swift发送邮件</a></li><li><a href="http://www.foolbirds.com/batch-in-symfony12.html" title="symfony1.2下的命令行程序(batch)">symfony1.2下的命令行程序(batch)</a></li><li><a href="http://www.foolbirds.com/generate-admin-templates-structure.html" title="symfony1.2的后台(generate-admin)模板结构">symfony1.2的后台(generate-admin)模板结构</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.foolbirds.com/redirect-and-forward-in-symfony.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

