View

第一節

View

view就是網頁的模板,它的檔名通常跟者呼叫它的action名稱命名。 例如,PostsController::add()呼叫的view就放在/app/views/posts/add.thtml。 Cake的view都是一些十分簡單的PHP檔,可以使用任何的PHP程式碼。 雖然說view檔的內容大部分都是HTML,但其實可以依需求放不同形式的資料,如XML或影像等等。

view裡可以使用來自Model的資料。 這些資料被放在名為$data的陣列裡。 而在controller中透過set()傳給view的所有資料也都可以在view裡使用。

HTML helper預設可以在每個view裡使用,它也是到目前為止最常被用到helper。 HTML helper對建立表單,嵌入script,放置媒體,連結與協助資料檢驗等都非常有幫助。 "Helpers"一章會仔細討論HTML Helper的功用,現在就不多說了。

view裡能用的大部分功能都是由Helper提供。 Cake附了一組功能強大的helper(Helper章節再討論),你也可以使用自己設計的。 因為view裡不應該含有太多的邏輯,所以view這個類別也就沒有太多公開的函式。 有一個叫renderElement(),在後面介紹Element時會詳細說明。

Layout(版形)

Layout的程式碼負責產生包圍在view周遭的版面物件。 只要是想讓所有的view都看到的東西,就應該放在Layout裡。

Layout的檔案放在/app/views/layouts目錄內。 Cake預設使用的Layout存放在/app/views/layouts/default.thtml檔。 你可以自己設計default.thtml,成為預設使用的Layout。 建立新的Layout之後,controller 的view就會被畫在裡頭。

當你建立Layout時,必須告訴Cake要將controller顯示的view放在那裡: 要做這件事,請確定Layout裡有地方放了$content_for_layout(和另一個叫$title_for_layout)。 這裡有個預設Layout的範例:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title><?php echo $title_for_layout?></title>
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
</head>
<body>

<!-- 若想在每個view上顯示選單,就放在這兒 -->
<div id="header">
    <div id="menu">...</div>
</div>

<!-- 這兒是我的view要顯示的地方 -->
<?php echo $content_for_layout ?>

<!-- 在每頁放上一個頁尾 -->
<div id="footer">...</div>

</body>
</html>
 

要幫Layout定一個標題,最簡單的方法是在controller裡,使用controller的$pageTitle變數定。

class UsersController extends AppController
{
    function viewActive()
    {
        $this->pageTitle = 'View Active Users';
    }
}

同一個Cake網站裡可以含有一大堆Layout。 這些Layout全被放在app/views/layouts裡,再透過controller的$layout變數或setLayout()函式選擇使用。

例如,我想要在網站上放一個小小的廣告,那麼我會建立一個有預留廣告空間的Layout, 然後讓每個controller的action指定使用它,程式像這樣:

var $layout = 'default_small_ad';

Element

很多程式都有一些小小的程式碼,重覆在每頁顯示些東西,有時候會顯示在Layout的不同地方。 Cake可以幫你重用這些部分。這些可重用的部分,就叫Element。 廣告,說明,流覽列,選單等在Cake裡都是用element實作。 Element可以視為可放在view裡的迷你view。

Element生活在/app/views/elements/資料匣裡,以.thtml為附檔名。

Element預設並沒有任何資料可以使用。 要給他資料,必須將參數放陣列裡傳過去。

譯註:雖然作者是這麼說,但實際上Element可以直接使用View裡的變數,除非是View中沒有的變數才需要靠這種方式傳。

呼叫Element,不含參數

<?php echo $this->renderElement('helpbox'); ?>

呼叫Element,包含參數

<?php echo
$this->renderElement('helpbox', array("helptext" => "Oh, this text is very helpful."));
 ?>
在Element裡使用參數,必須將參數名稱當成陣列的鍵將值取出才能使用(跟controller用set()把值傳給view類似)。 在上面的例子裡,/app/views/elements/helpbox.thtml裡可以使用$helptext變數。 當然,如果傳的是陣列會更有用。

Element把會重覆的元素放在自己所屬的檔案中,讓view的程式碼更具可讀性。 它們也能幫助你重用網頁裡重覆的小片段。


附錄:讀者筆記

view不能存unicode? 

小瓜呆說:我用ultraedit選File->Convertion->Ascii to Unicode 將view的thtml存檔, CakePHP讀不出來, 有法子嗎?

Clar回答說:我試了一下, 得用Convertion->ASCII to UTF-8(Unicode editing)才行

Element內使用變數 

Clar說:雖然手冊上說:Element預設並沒有任何資料可以使用。但實際上在view裡使用時,卻發現預設可以使用view的變數。如果controller裡呼叫$this->set('var',3); view裡就可以使用$var, view裡又呼叫了$this->renderElement('helpbox'); 則helpbox裡就可以使用$var。可能是現在版本已修改這個行為吧?

ecoogo回答說:大大說element裡可以使用view的變數,不過我實際操作後,還是不行ㄝ,仍然要靠renderElement在後面加上要傳入的陣列,才能把view變數傳到element。不過全域變數,則不用傳也可以用。 可否請大大再確認一下,謝謝!

Clar回答說:我再重新測試了一下程式, 還是可以.

Jeely回答說:若想要傳參數給 Element . 只要在 view 的程式中呼叫 Element 的函式中加上 array 就可以了 比方說: index.thtml $this->element('msgbox',array("content"=>"Error!!")) 那麼在 msgbox.ctp 這個 Element 就可直接使用 $content 的變數 參考官網 http://book.cakephp.org/view/94/views#elements-97

一个action一定要一个view文件吗 

刘德华說:一个action一定要一个view文件吗?我想在一个ACTION成功后 直接返回到当前页面,刷新当前页面,比如删除一条记录,用一个 delete action 直接刷新当前页面 !

Clar回答說:Method不一定要有VIEW, 可以直接用Controller裡的redirect(url) 直接轉向到你要去的URL就行, 或用Controller的flash()也行

有關Layout跟Css 

自由的風說:一直都有一個問題就是我現在要用一個新的layout不過套用了之後我不知道如何把CSS檔include進來

view內容的*.thtml檔名必需小寫 

liaosankai說:最近開發程式中發現當我把某個view的檔名取為uploadImage.thtml時,Controller將無法render它。於是我猜是不是有關鍵字?upload不能用?(應該不會吧=_=),所以我試著將檔名改成 myTest.thtml然後去測試,結果…還是沒辦法把畫面render出來。最後我發現一個地方 就是view的資料夾的檔名好像都是小寫,所以再測試一次把檔名改成mytest.thtml,結果可以了耶,再確認一次把檔名改成uploadimage.thtml,結果也可以了。所以這邊提醒大家view中的檔名,請全部使用小寫,才不會有問題。 以上心得,如果有不對之處請指正,謝謝。