多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > 數據庫 > access > symfony24天教程之第4天 重構

symfony24天教程之第4天 重構

來源:程序員人生   發布時間:2014-09-28 07:49:33 閱讀次數:6887次

 symfony回顧

在第3天,我們看到了一個MVC架構的所有層,并修改它們用來在頁面上正確地表示question的列表。應用變得好看了些但是還是有點缺乏內容。第四天的目標是表示一個question的answer,給question的詳細頁面一個更友好的URL,加入一個客戶類(custom class),路由政策,以及重構。你可能覺得現在就重寫前幾天的代碼有點太早了,但是相信完成了今天的教程之后你的想法會有所改變。

要閱讀這個教程,你應該熟悉以下的章節 MVC在symfony中的實現 .還有如果你懂一點 敏捷開發 也會有所幫助。

表示一個quesiton的answer

首先,讓我們繼續調整第2天Question CRUD生成的模板。quesiton/show 動作專注于表示一個quesiton的詳細信息,并假設收到的參數是你傳給它的id。我們可以試試看,調用下面的URL(你可能要把最后的 2 改成你的數據表里的某個id)

http://askeet/frontend_dev.php/question/show/id/2

你可能已經開到過這個頁面了。這就是我們將要修改的頁面,我們要加上一個question的answer.

動作速覽

首先,讓我們看看show動作,它在下面這個文件。

askeet/apps/frontend/modules/question/actions/actions.class.php

public function executeShow()
 {
   
$this->question = QuestionPeer::retrieveByPk($this->getRequestParameter('id'));
   
$this->forward404Unless($this->question);
 }

如果你熟悉Rropel,你知道這是一個簡單的對Question數據表的請求。它的目的是用id參數作為唯一主鍵取得一條唯一的記錄。在上面這個例子里,id參數的值是2,所以QuestionPeer類的->retrieveByPk()方法會返回一個Question類的對象,它的主鍵為2。如果你不熟悉Propel,那么請先看看 某些文檔,然后再回來繼續。

這個請求的結果被通過$question變量交給 showSuccess.php模板,

sfAction對象的->getRequestParameter('id‘)方法取得請求中的叫做'id'的參數,而不論它是通過GET還是POST模式傳來的。例如,如果你請求

http://askeet/frontend_dev.php/question/show/id/1/myparam/myvalue
那么show動作將用 $this->getRequestParameter('myparam').來取得myvalue.

注意:forward404Unless()方法如果在數據庫找不到要找到question它就會發送給瀏覽器一個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>

你看到interested_block div在昨天已經加到listSuccess.php模板了。它表示對一個question感興趣的用戶數。還有,現在它非常象一個list,除了在title沒有link_to.它只是對初始代碼的一次改寫,以表示一個question的需要表示的信息。

新的部分是answers  DIV,它表示對這個question的所有answer(用 $question->getAnswers() Propel方法),除了body還表示每個answer的Relevancy(關聯),作者的名字,創建日期。

format_date()是另一個需要初始聲明的模板助手的例子,你可以在 symfony寶典的 助手的初始化 章節找到更多關于助手的語法。(這些助手幫助我們能更快地完成單調的日期格式化表示的任務)

注意:Propel為關聯表創建的方法的名字是在表名后加一個's',雖然->getRelevancys() 這樣的方法名有點不好看,但是可以幫你節約號幾行SQL代碼。

加入一些新的測試數據

現在是時候在 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

如果以前修改成功,下面的URL將將表示你的第一個question

http://askeet/frontend_dev.php/question/show/id/XX
注意:把XX改成你的第一個question的id

現在 question表示得更好看了,后面還跟著它的answer.不錯吧。

修改模塊 第1部分

幾乎可以肯定表示一個作者的全名在這個應用的其他地方也會用到。你也可以把全名考慮成一個User對象的屬性,這意味著User模塊應該有一個方法可以用來取得全名,而不是在動作中每次重寫。打開 askeet/lib/model/User.php 加入以下的方法

public function __toString()
{
  
return $this->getFirstName().' '.$this->getLastName();
}

為什么這個方法叫 __toString() 而不叫 getFullName()或其它類似的名字呢?因為__toString() 方法在PHP5中是一個對象描述為字符串時的缺省方法。這意味著你可以把askeet/apps/frontend/modules/question/templates/showSuccess.php 文件里的下面的代碼改寫成 更簡單的形式

posted by <?php echo $answer->getUser()->getFirstName().' '.$answer->getUser()->getLastName() ?> 
改為
posted by <?php echo $answer->getUser() ?> 

代碼簡潔吧.

不要重復你自己

敏捷開發的一個好的原則就是避免重復代碼,被稱為 Don't Repeat Yourself (D.R.Y)。這是因為重復的代碼在檢查,修改,測試和更新的時候都要比一段封裝后的代碼多花更多的時間。這還讓應用的維護變得復雜。如果你去看看昨天的教程,你會注意到昨天寫的listSuccess.php模板和ShowSuccess.php有一些重復的代碼。

<div class="interested_block">
  
<div class="interested_mark">
    
<?php echo count($question->getInterests()) ?>
  
</div>
</div>
 

所以我們重構的第一個任務就是去掉這兩個模板里的重復代碼,把他們放到一個片段(fragment),或成為可重用代碼塊里。在askeet/apps/frontend/modules/question/template/ 里創建一個_interested_user.php文件,代碼如下。

<div class="interested_mark">
  
<?php echo count($question->getInterests()) ?>
</div>

然后,把兩個模板(listSuccess.phpshowSuccess.php)里的代碼置換成

<div class="interested_block">
  
<?php include_partial('interested_user', array('question' => $question)) ?>
</div>

一個片段沒有任何對現在對象的本地訪問,這個片段用了一個 $question變量,所以它必須在對 include_partial 的調用里定義。片段文件的前綴_可以幫助我們把它和template/目錄下的真正的模板文件區分開來。如果你想學到更多關于片段的知識,可以讀一讀 symfony寶典的 顯示 章節

修改模塊 第2部分

新的片段里的$question->getInterests()調用請求數據庫并返回一個Interest類的對象的數組。對于只需要感興趣的用戶的數字來說這是一個消耗太大的請求,它可能給數據庫帶來不必要的負載。記住,這個調用還在listSuccess.php里調用,是在一個循環里。看來最好優化一下它。

一個好的方法是給Question數據表加入一個叫做interested_users的列,然后在每次有關于這個question的interest創建的時候去更新這個列。

重要:我們將要更改一個模塊,但是沒有明顯的方法去測試它,因為現在沒有辦法可以去通過askeet給Interest數據表加記錄。如果你沒法測試,你就不應該做任何修改。幸運的是,我們有一個辦法可以測試這個修改,我們會在本章的后面發現它。

給User對象模塊加入一個字段

大膽地修改the askeet/config/schema.xml 數據模塊,給ask_question數據表加一個字段。

<column name="interested_users" type="integer" default="0" />

然后重建模塊

$ symfony propel-build-model

對,我們重建模塊而不用擔心對現有模塊的擴展,因為對User類的擴展是在 askeet/lib/model/User.php里的,它繼承自Propel 生成的類askeet/lib/model/om/BaseUser.php。這就是你為什么不應該編輯 askeet/lib/model/om/ 目錄下的代碼:它們在每次調用build-model的時候都被重建。Symfony幫助我們更容易地在Web項目的早期修改模塊。

你好需要更新真實的數據庫。為了避免寫SQL語句,你要重建你的SQL schema并重新載入測試數據

$ symfony propel-build-sql
$ mysql -u youruser -p askeet < data/sql/lib.model.schema.sql
$ php batch/load_data.php

注意:TIMTOWTDI(另一種方法,There is more then one way to do it):除了重建數據庫,你可以手工給MySQL數據表加入新的列。

$ mysql -u youruser -p askeet -e "alter table ask_question add interested_users int default '0'"

修改Interest對象的保存方法

更新這個新字段的動作必須在每次一個user對一個question感興趣的時候都做一次,也就是說,每次一條新的紀錄加入到Interest數據表的時候都要做一次。你可以通過在MySQL里做一個觸發器來實現它,但是這是一個數據庫依存的解決方案,你就不能很容易地遷移到另一個數據庫了。

最好的解決方案是重載Interest類的save()方法,這個方法每次Interest的對象被創建的時候都會被調用。所以,打開 askeet/lib/model/Interest.php ,寫如下的代碼


 

public function save($con = null)
{  
    
$ret = parent::save($con);
 
    
// update interested_users in question table
    $question = $this->getQuestion();
    
$interested_users = $question->getInterestedUsers();
    
$question->setInterestedUsers($interested_users + 1);
    
$question->save( 生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 日本欧美韩国 | 欧美成a人片在线观看 | 日韩一级片视频 | 国产精品国产午夜免费福利看 | 亚洲一区二区三区免费视频 | 国产精品久久久久久久久免费观看 | 亚洲男人天堂2022 | 最新毛片久热97免费精品视频 | 成人精品一区二区激情 | 一级欧美 | 1314成人网 | 我爱52av好色 | 免费一级毛片清高播放 | 欧美成人免费全部观看天天性色 | 国产高清在线精品一区a | 国产成人精品日本亚洲专一区 | 91欧美精品综合在线观看 | 另类专区国产在线视频 | 男女视频免费网站 | 欧美日韩国产综合在线小说 | 午夜免费视频网站 | 久久中文字幕不卡一二区 | 拍拍拍无挡视频免费全程1000 | 国产农村女人一级毛片了 | 亚洲国产第一区二区三区 | 一区二区三区欧美在线 | 精品国产乱码久久久久久一区二区 | jizz亚洲大全 | 成 人国产在线观看高清不卡 | 亚洲精品美女久久久久 | 亚洲欧美在线不卡 | 国产精品免费久久久久影院小说 | 亚洲精品第四页中文字幕 | 满18看的毛片 | 免费看逼逼 | 国产麻豆剧看黄在线观看 | 免费一级欧美毛片 | 网站久久| 免费观看wwwwwww | 最近新中文字幕大全高清 | 日本 欧美 在线 |