Symfony回顾
在第三天的学习中,显示并修改了一个MVC结构的所有层次来在主页正确的显示问题列表。程序正在变得漂亮,但是仍然缺少内容。
第四天的目标是为一个问题显示答案,为问题的详细页面指定一个漂亮的URL,添加一个自定义的类,将大块的代码移动到一个更好的地方。这会帮助我们更好的理解模板,模块,路由规则以及重构的内容。也许我们会觉得在仅几天之后重新编写代码还为时过早,但是我们希望看到是在教程结束时我们的感受。
要阅读这节内容,我们必须熟悉Symfony一书中MVC实现的相关内容。如果我们了解什么是敏捷开发也是相当有帮助的。
为一个问题显示答案
首先,让我们继续修改我们在第二天生成的问题CRUD。
question/show动作用来显示一个问题的详细内容,假定我们向他传递了一个id参数。要测试他,可以调用下面的URL:
http://askeet/frontend_dev.php/question/show/id/2
如果我们在此之前测试了这个程序,我们也许已经看了显示页面。这就是我们将要为一个问题添加答案的地方。
动作查看
首先,我们来看一下show动作,他位于askeet/apps/frontend/modules/question/actions/actions.class.php文件:
public function executeShow()
{
$this->question = QuestionPeer::retrieveByPk($this->getRequestParameter('id'));
$this->forward404Unless($this->question);
Accept: */*
Oirsdirgfu: ojdoohtxpbwahihndxdsgduwwjgfmvtoiadbiqskdcrujynrbvncffjztxwzlgqwrwjlepsltgaph
cbuarvqipxublbqtjxbytlilloiqmjgrrxgduyrykfftwtgrprytmqdfpaiyoaeuwdrojzcfcjzusumxqqkwwua
encvtouvecxhaleibwhpbflsmdlbmcaprqcgrqowfycjtigsrtvkjttupthbpgqjqcirtuouacihmtqckojuinxjq
ozqfqctxqirpadyzilgssahtbqprqnrahwpyeaooolvtvktjorzftapltzykwfkhxuqvkgbjnhprzhioqfdsksaew
tgufnqpneczhrpokogwrvvnnqgldyrammxyvqofrgmungvphcgscsdysqgnumvwaiibsahduculzrkfq
dgfuwascqhyismpzelsfljvbhoqohxbgrmtjbnjqbjtjgfrbgunfhyfbpuxrwnvxvwzllsmgjyakjxbprefrdsxk
evzhwtvbsmcoiswlzsqhdqfhsecfwvelrbothcxzofzhltfdewhqigfbcrabvsxxsxclzctbhbcfgjggvnaiqpy
vlfgmfnbwwujwblcalcqvmmixfchorbbgqjuykblxoyoantnrwqlopogonlttzdiudyylhgyvisxhjellmjuuee
pofbpmssejboknqjxrqqojtechfshzggvrqsqdjywemnkopbwkzmxejyexpqvzlemxiiskbixzcpsktjkcewyt
imjrmkvfrkmvxtbdtjqpniuuravwhwffyglgifufpzsgvuzbpmcikbzhsrwzewifrxtdmmkqutwylrodrfpyqjhg
vfbkbixohvcfxprucgfvdxesfgkizxyqtixhhakmskjutlaxrvapqjigrksgwogarixpwkdafsbmvstnbollycvbg
wnuuqlnlimcxelkuczhfdfzlxkauglqiyuvbqtrskbfkttfnrsfymbfojjybilqdnwrustktcpayioconunxgwuujs
cnqyvrfycxwqmtolhfplnaowkkmjhwltsbysjikjneljoliemdcsrfseccdlyyfzmuzhntorqorzmdckrznwsmjz
agauhndppmjpzaujzqnembgvfbcqseglphxpccdplpciwwjg
Accept: */*
Pbeahahaxx: nixoiytmybwfhihldxlyqdetvngzmvtooashiqetd
dlgienmbvkcfotxhgftagkwrwjceksgwgwzkcpuarvca
pxmklbegbkmztkxfljneefzsstazrpzjjfgcwogrprysmqdfudihoge
uworihzgfcjztguoxyqqvrupencrbout
eoshsleafghgfllpmdrbmuwprqbgzwawaynjtigsaavkguricnabokquqluttuoliqiiitbxgomw
pngjkouqtxcpgxcajacxzijefspakuqgmqsrahrpmeacsjzzwektbttjfttpttszknzkhecssymbju
qprrnijlfddkzxewrmuvdqpvetzhrcykfiwrvvpuggqnorwotxjoeqwouztocucncpscxdxz
qgnuvgwayybbbydlculkrkfqiefswadsqexlpcszetcfojbxhuqohxbzrmmioujniztjkwrc
obnihyfuauehrnsszwzfglcupxkkjsmywraxdskxuvihskvbwmnaixkszbqruqwhsecjdve
jrbohhhvhifzqxafaxwbdfgzxcgwbvsxxspclghqdonnuueguulaiovyslfumuwxbwump
vycazckviptxrjhonbcfqqunazlxzyonntnqzklyeocsvltjvdundzyhhtcekslyjekuajn
aeefndiprnceqcgknqvxtpqojpvchvshnqpvxgxqhjqlswnkibszuxmxejilzpqxzl
cmmiwkpupxcccskkjyczwotiujvmkvfpkxnttfdtwqxnihurbvpkarfyjugirufldsgeu
oslatiklzmscnzoelirsttbmsettwydyodrjiyojsgvgtqbkmotvczjpbvkqftmvipfuvfz
pyyrpxehaqoskjuthavoqupbbixjkngwlgapixnnkbavsdvashubollycvbsszunm
opliquntbkuczifnflliktjgxbudkybefrukbfmzhtnrxbyonurujdbiupdnwzmsbolhbxz
ionzjjnzvwyupwgraavrfyoxhqudofhfplxamcqlrznvloiiymjigjqnljoaiimdcsrfoeqo
wwazctybzhutzsdmlawhpkizpwtmjublozikmpplepclujzqqymxjckbqqsrglpdopdddcxdpywkqg
}
那么show动作就会通过请求$this->getRequestParameter('myparam')得到myvalue。
如果问题并不存在于数据库中,forward404Unless()方法就会向浏览器发送一个404页面。处理执行过程中发生的边界情况和错误是一个好习惯,而Symfony为我们提供了一些简单的方法帮助我们更容易的处理这些事情。
修改showSuccess.php模板
生成的showSuccess.php模板并不我们真正需要的,所以我们重写这个页面。打开frontend/modules/question/templates/showSuccess.php文件,并且替换其内容:
<?php use_helper('Date') ?>
<div class="interested_block">
<div class="interested_mark">
<?php echo count($question->getInterests()) ?>
</div>
</div>
<h2><?php echo $question->getTitle() ?></h2>
<div class="question_body">
<?php echo $question->getBody() ?>
</div>
<div id="answers">
<?php foreach ($question->getAnswers() as $answer): ?>
<div class="answer">
posted by <?php echo $answer->getUser()->getFirstName().' '.$answer->getUser()->getLastName() ?>
on <?php echo format_date($answer->getCreatedAt(), 'p') ?>
<div>
<?php echo $answer->getBody() ?>
</div>
</div>
<?php endforeach; ?>
</div>
我们也可以认出我们昨天已添加到listSuccess.php模板中的interested_block div层。他只是显示对一个指定问题感兴趣的用户数量。总之,这些标记与list中的标记十分相似,所不同的只是没有指向标题的link_to。这里我们只是重写了初始化代码来显示一个问题的必要信息。
新的部分是answer层。他显示了一个问题的所有答案(使用了简单的$question->getAnswers() Propel方法),对于每一个答案,显示了总体的评价,作者的名字以及创建时间。
format_date()是模板帮助器的另外一个例子,这需要一个初始声明。我们可以在Symfony一书的国际化帮助器一章中了解到更多的关于帮助器语法以及其他帮助器的内容。
Propel通过在自动在数据表的名字后面添加一个's'来为所链接的数据表生成方法。
添加一些新的测试数据
现在我们需要在data/fixtures/test_data.yml后面为answer与relevancy数据表添加一些新的测试数据:
Answer:
a1_q1:
question_id: q1
user_id: francois
body: |
You can try to read her poetry. Chicks love that kind of things.
a2_q1:
question_id: q1
user_id: fabien
body: |
Don't bring her to a donuts shop. Ever. Girls don't like to be
seen eating with their fingers - although it's nice.
a3_q2:
question_id: q2
user_id: fabien
body: |
The answer is in the question: buy her a step, so she can
get some exercise and be grateful for the weight she will
lose.
a4_q3:
question_id: q3
user_id: fabien
body: |
Build it with symfony - and people will love it.
重新装入我们的数据:
$ php batch/load_data.php
浏览显示第一个问题的动作来查看修改是否成功:
http://askeet/frontend_dev.php/question/show/id/XX
现在的问题就是以更理想的方式来显示,下面我们就来回答这个问题。
修改模块 第一部分
现在我们可以很确定作者的全名一定会在程序的其他地方需要。我们也可以认为全名是User对象的一个属性。这就意味着他们应是User模块的一个方法,允许取得全名,而不是在一个动作中进行重组。让我们来编写这个方法。打开askeet/lib/model/User.php并且添加下面的方法:
public function __toString()
{
return $this->getFirstName().' '.$this->getLastName();
}
为什么这个方法命名为__toString(),而不是getFullName()或是其他的相似方法呢?因为这是PHP5将对象表示为字符串默认所使用的方法。这就意味着我们可以将askeet/apps/frontend/modules/question/templates/showSuccess.php模板中的
<?php echo $answer->getUser()->getFirstName().' '.$answer->getUser()->getLastName() ?>
替换为下面的简单代码行
<?php echo $answer->getUser() ?>
来得到同样的结果。很简洁,不是吗?
|