CakePHP 2.x CookBook 中文版 第六章 視圖 之二

 

主題

主題可以使你快捷地切換頁面的外觀。

要使用主題,只需在控制器中指定主題名稱:

class ExampleController extends AppController {
    public $theme = 'Example';
}

在 2.1 版更改: 2.1 以前的版本需要使用 $this->viewClass = 'Theme' 設置主題。 2.1 刪除了這一要求,並在正常的 View 類中支持主題。

也可以在動作或者 beforeFilterbeforeRender 回調中設置或改變主題:

$this->theme = 'AnotherExample';

主題視圖文件要放在 /app/View/Themed/ 文件夾。在主題文件夾中,使用與主題相同的名字建立文件夾。例如,上面的主題存放在 /app/View/Themed/AnotherExample。 重要的是要記住 CakePHP 期望主題名遵循駝峯命名法。此外,/app/View/Themed/Example/ 文件夾的結構就與 /app/View/ 文件夾相同。

例如,Posts 控制器的 edit 動作所渲染的視圖文件是 /app/View/Themed/Example/Posts/edit.ctp。佈局文件則存放在 /app/View/Themed/Example/Layouts/

如果主題中沒有某個視圖文件,CakePHP 就嘗試在 /app/View/ 文件夾中尋找它。如此一來,你只需要在主題文件夾中根據實際情況建立主要的視圖來簡單的覆蓋需要覆蓋的視圖文件。

Theme 部件

主題能夠包含靜態部件和視圖文件。 一個主題可以在它的 web 根目錄包含所需的部件。這樣就更易於打包和發佈主題。在開發中,主題部件的請求將被 Dispatcher 處理。爲了在生產環境中提高運行效率,推薦符號鏈接或複製主題部件到應用程序的 web 根目錄。更多信息參見後文。

在主題中建立類似 app/View/Themed/<themeName>/webroot<path_to_file> 的文件夾來使用新的主題 web 根目錄。分發器將處理在視圖路徑中找到的當前主題部件。

CakePHP 內置的所有助手都支持主題並自動建立正確的路徑。 像視圖文件一樣,如果主題文件夾中不存在某些助手需要的文件,將到主根目錄中尋找它們:

// 在名爲 'purple_cupcake' 的主題中
$this->Html->css('main.css');

// 建立如下的文件
/theme/purple_cupcake/css/main.css

// 並鏈接到
app/View/Themed/PurpleCupcake/webroot/css/main.css

提高插件和主題部件的運行效率

一個衆所周知的事實是,通過 PHP 調用處理部件要比不通過 PHP 調用慢。在需要更高的運行效率的場合,核心團隊已經採取了一些措施讓插件和主題部件儘可能地快速運行。此時,推薦你建立符號鏈接或者複製 插件/主題部件到app/webroot ,並通過 CakePHP 匹配這些路徑。

  • app/Plugin/DebugKit/webroot/js/my_file.js 變成 app/webroot/DebugKit/js/my_file.js
  • app/View/Themed/Navy/webroot/css/navy.css 變成 app/webroot/theme/Navy/css/navy.css

媒體視圖

class MediaView

2.3 版後已移除: 被 傳輸文件 取代。

媒體視圖允許你向用戶傳送二進制文件。例如,你可能希望有一個位於 web 根目錄之外的禁止用戶直接鏈接的文件目錄。你可以使用媒體視圖從 /app/ 下的一個特定文件夾中提取文件,允許你在將文件交給用戶前執行權限驗證。

要使用媒體視圖,你只需告訴控制器用媒體視圖類取代默認的視圖類。然後在附加參數中傳遞媒體視圖文件的位置:

class ExampleController extends AppController {
    public function download() {
        $this->viewClass = 'Media';
        // Download app/outside_webroot_dir/example.zip
        $params = array(
            'id'        => 'example.zip',
            'name'      => 'example',
            'download'  => true,
            'extension' => 'zip',
            'path'      => APP . 'outside_webroot_dir' . DS
        );
        $this->set($params);
    }
}

下面是一個渲染視圖 $mimeType 數組中不存在的媒體類型的文件的例子。我們也可以使用相對於 app/webroot 文件夾的相對路徑:

public function download() {
    $this->viewClass = 'Media';
    // Render app/webroot/files/example.docx
    $params = array(
        'id'        => 'example.docx',
        'name'      => 'example',
        'extension' => 'docx',
        'mimeType'  => array(
            'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
        ),
        'path'      => 'files' . DS
    );
    $this->set($params);
}

可設置的參數

id
ID 是文件在文件服務器中的命名(包含擴展名)。
name
這個名字允許你指定一個傳送給用戶的備用文件名。不需要指定擴展名。
download
這個邏輯值決定傳遞的文件頭信息中設置是否允許下載。
extension
文件的擴展名。它與內部可接受的 mime 類型列表匹配。如果指定的 mime 類型不在列表中,此文件將不能被下載。
path
文件夾的名字,包含最後的路徑分隔符。這個路徑將是絕對的,除非它相對於 app/webroot 文件夾。
mimeType
一個附加的 mime 類型數組,它將與媒體視圖內置的可接受列表合併。
cache
一個邏輯值或者整數值 - 如果設置爲 true,就表示允許瀏覽器緩存此文件(如果沒有設置,則默認爲 false);如果將其設置爲數字,則爲緩存過期的時間,以秒爲單位。

JSON 和 XML 視圖

CakePHP 2.1 是有兩個新的視圖類。XmlView 和 JsonView 讓我們更易於建立 XML 和 JSON 響應,並與RequestHandlerComponent 整合。

通過在應用程序中允許 RequestHandlerComponent ,和允許支持 xml 和/或 json 擴展,你可以自動利用新的視圖類。XmlView 和 JsonView 此頁的剩餘部分以數據視圖來引用。

有兩種生成數據視圖的方法。一種是通過使用 _serialize 鍵,一種是通過建立正常的視圖文件。

在應用程序中允許使用數據視圖

在使用數據視圖類之前,需要做些設置:

  1. 利用 Router::parseExtensions() 允許 json 和/或 xml 擴展。這將允許路由處理多個擴展。
  2. 在控制器的組件列表中添加 RequestHandlerComponent 。這會自動允許視圖類在內容類型間切換。你可以使用viewClassMap 選項設置組件,映射類型到自定義的類 和/或 映射其它數據類型。

2.3 新版功能: 增加了 RequestHandlerComponent::viewClassMap() 方法用於映射類型到視圖類。 viewClassMap 選項在之前的版本中也不工作。

在向路由文件添加 Router::parseExtensions('json'); 後,CakePHP 將在收到以 .json 結束的或者帶有application/json 頭信息的請求時自動切換視圖類。

利用 serialize 鍵使用數據視圖

_serialize 鍵是一個特殊的視圖變量 - 表明在使用數據視圖時其它的視圖變量將被序列化。 如果在數據轉換成 json/xml 之前,你不需要做自定義格式化,這種方式就可以讓你跳過爲控制器動作定義視圖文件這一步。

如果在生成響應之前需要格式化或操縱視圖變量,你就需要使用視圖文件。_serialize 的值可以是準備序列化的一個字符串或者一個視圖變量數組:

class PostsController extends AppController {
    public function index() {
        $this->set('posts', $this->paginate());
        $this->set('_serialize', array('posts'));
    }
}

你也可以將 _serialize 定義爲一個用於綁定的視圖變量數組:

class PostsController extends AppController {
    public function index() {
        // some code that created $posts and $comments
        $this->set(compact('posts', 'comments'));
        $this->set('_serialize', array('posts', 'comments'));
    }
}

當使用 XmlView 時,以數組方式定義 _serialize 有一個附加的好處,自動添加一個頂級的 <response> 元素。 如果在使用 XmlView 時使用 _serialize 的字符串值,先確認你的視圖變量有一個單獨的頂級元素。不帶單獨的頂級元素,Xml 無法生成。

利用視圖文件使用數據視圖

如果在建立最終的輸出前需要做一些視圖內容的操作,你可能需要使用視圖文件。例如,如果我們有 posts,其中一個域包含生成 HTML,我們可能想要忽略 JSON 輸出。這時,視圖文件就派上了用場:

// 控制器代碼
class PostsController extends AppController {
    public function index() {
        $this->set(compact('posts', 'comments'));
    }
}

// 視圖代碼 - app/View/Posts/json/index.ctp
foreach ($posts as &$post) {
    unset($post['Post']['generated_html']);
}
echo json_encode(compact('posts', 'comments'));

你能做更多更多地複雜操作,也可以使用助手進行格式化。

註解

數據視圖類不支持佈局。它們假定視圖文件將輸出序列化內容。

class XmlView

一個生成 Xml 視圖數據的視圖類。見上文如何在應用程序中使用 XmlView。

當使用 _serialize 時,XmlView 默認將使用一個 <response> 節點包含你的序列化視圖變量。你可以藉助 _rootNode視圖變量爲這個節點指定一個自定義名稱。

2.3 新版功能: 增加了 _rootNode 特性。

class JsonView

一個生成 Json 視圖數據的視圖類。風上文如何在應用程序中使用 JsonView。

助手

助手是應用程序顯示層中類似組件的類。它們包含在多個視圖、元素或佈局間共享的顯示邏輯。這一章將向你展示如何建立你自己的助手,並且描述了 CakePHP 的核心助手能幫助你實現的基本任務。

CakePHP 包含了一些幫助建立視圖的助手。 它們協助建立格式良好的標籤(包括表單),幫助格式化文本、時間和數字,甚至還能爲 Ajax 功能提速。關於 CakePHP 中的助手的更多信息,請瀏覽 助手 。

使用和配置助手

在 CakePHP 中,你可以通過讓控制器知道助手的存在來使助手可用。 每個控制器有一個 $helpers 屬性,列出了可以在視圖中使用的助手。要使一個助手在視圖中可用,將這個助手的名字添加到控制器的 $helpers 數組:

class BakeriesController extends AppController {
    public $helpers = array('Form', 'Html', 'Js', 'Time');
}

在 CakePHP 的其它位置,添加插件內的助手請使用 插件語法

class BakeriesController extends AppController {
    public $helpers = array('Blog.Comment');
}

你還可以在動作內添加助手,這樣它們就只在這個動作中可用,但在同一控制器的其它動作中無法使用。這會節省那些不需要助手的動作的計算能力,同時保持控制器的良好組織:

class BakeriesController extends AppController {
    public function bake {
        $this->helpers[] = 'Time';
    }
    public function mix {
        // Time 助手不加載,也不能使用
    }
}

如果需要在所有的控制器中使用一個助手,將其加入到 /app/Controller/AppController.php 文件的 $helpers 數組中(如果它不存在,就創建一個)。記住,包含默認的 Html 和 Form 助手:

class AppController extends Controller {
    public $helpers = array('Form', 'Html', 'Js', 'Time');
}

你可以傳遞選項給助手。這些選項能夠被用於設置屬性值或者修改助手的行爲:

class AwesomeHelper extends AppHelper {
    public function __construct(View $view, $settings = array()) {
        parent::__construct($view, $settings);
        debug($settings);
    }
}

class AwesomeController extends AppController {
    public $helpers = array('Awesome' => array('option1' => 'value1'));
}

2.3 版的選項合併了助手的 Helper::$settings 屬性。

一個公用的設置是 className 選項,它允許你在視圖中建立助手別名。這個特性在你想要替換 $this-Html 或者引用自定義實現的其它公用助手時很有用:

// app/Controller/PostsController.php
class PostsController extends AppController {
    public $helpers = array(
        'Html' => array(
            'className' => 'MyHtml'
        )
    );
}

// app/View/Helper/MyHtmlHelper.php
App::uses('HtmlHelper', 'View/Helper');
class MyHtmlHelper extends HtmlHelper {
    // Add your code to override the core HtmlHelper
}

上面的代碼將視圖中的 MyHtmlHelper 的別名設置爲 $this->Html 。

註解

爲助手定義別名將在所有使用別名的位置替換其實例,包括在其它助手中。

小技巧

在使用核心的 PagesController 時,爲 Html 或者 Session 助手定義別名將無法工作。 最好是將lib/Cake/Controller/PagesController.php 複製到 app/Controller/ 文件夾。

使用助手設置允許你聲明配置助手,並在控制器動作之外維護配置邏輯。如果你有不能包含在類聲明中的配置選項,你可以在控制器的 beforeRender 回調中設置它們:

class PostsController extends AppController {
    public function beforeRender() {
        parent::beforeRender();
        $this->helpers['CustomStuff'] = $this->_getCustomStuffSettings();
    }
}

使用助手

一旦你已經在控制器中配置了你想使用的助手,它就成爲視圖中的公用屬性,如果你使用 HtmlHelper ,你就可以通過如下方式訪問它:

echo $this->Html->css('styles');

上面的代碼調用了 HtmlHelper 的 css 方法。人可以使用 $this->{$helperName} 訪問任何已加載的助手。有時你可能需要從視圖中動態加載一個助手。你可以使用視圖的 HelperCollection 來做到這一點:

$mediaHelper = $this->Helpers->load('Media', $mediaSettings);

HelperCollection 是一個 集合 ,並且支持在 CakePHP 的任意一處使用集合 API。

回調方法

助手包含幾個允許你提高視圖渲染能力的回調方法。更多信息參見 助手 API 和 集合 文檔。

創建助手

如果內核助手(或者展示在 github 和 Bakery中的)不能滿足要求,可以很容易的創建助手。

假設我們想要創建一個能夠用於輸出一個特別制定的在應用程序的許多位置需要的 CSS 風格的鏈接的助手。爲了適合你的邏輯及 CakePHP 現有助手結構,你需要在 /app/View/Helper 中創建一個新的類。調用我們的 LinkHelper 助手。這個真實的 PHP 類文件類似於:

/* /app/View/Helper/LinkHelper.php */
App::uses('AppHelper', 'View/Helper');

class LinkHelper extends AppHelper {
    public function makeEdit($title, $url) {
        // 建立特別格式的鏈接的邏輯放在這...
    }
}

註解

助手必須繼承 AppHelper 或者 Helper,也可以使用 助手 API 實現全部回調。

包含其它助手

你也許會希望使用其它助手中已經存在的功能。要做到這一點,你可以指定助手使用 $helpers 數組,格式與控制器中的格式類似:

/* /app/View/Helper/LinkHelper.php (using other helpers) */
App::uses('AppHelper', 'View/Helper');

class LinkHelper extends AppHelper {
    public $helpers = array('Html');

    public function makeEdit($title, $url) {
        // 使用 HTML 助手輸出
        // 格式化的數據:

        $link = $this->Html->link($title, $url, array('class' => 'edit'));

        return '<div class="editOuter">' . $link . '</div>';
    }
}

使用助手

一旦創建了助手,並放進了 /app/View/Helper/,你也可以在控制器中使用特別變量 $helpers :

class PostsController extends AppController {
    public $helpers = array('Link');
}

只要控制器知道這個新類的存在,你就可以在視圖中使用它(通過訪問以這個助手命名的對象):

<!-- 讓一個鏈接使用新助手 -->
<?php echo $this->Link->makeEdit('Change this Recipe', '/recipes/edit/5'); ?>

爲所有助手創建功能

所有的助手都繼承自一個特殊類 AppHelper(類似於所有的模型都繼承 AppModel 和所有的控制器都繼承 AppController)。要爲所有的助手創建功能,建立 /app/View/Helper/AppHelper.php 這個文件:

App::uses('Helper', 'View');

class AppHelper extends Helper {
    public function customMethod() {
    }
}

助手 API

class Helper

助手的基類。它提供了一些工具方法,和加載其它助手的功能。

Helper::webroot($file)

解析一個文件名到應用程序的 web 根目錄。如果一個主題激活並且此文件在當前主題的 web 根目錄中存在,到這個主題文件的路徑將被返回。

Helper::url($url$full = false)

創建一個 HTML 轉義 URL,委託給 Router::url() 方法。

Helper::value($options = array()$field = null$key = 'value')

得到給定的輸入名的值。

Helper::domId($options = null$id = 'id')

爲當前選擇的域生成一個駝峯命名的 id 值。 在 AppHelper 中覆蓋這個方法允許你改變 CakePHP 生成 ID 屬性的方式。

回調

Helper::beforeRenderFile($viewFile)

在所有的視圖文件被渲染前調用。 包括元素、視圖、父視圖和佈局。

Helper::afterRenderFile($viewFile$content)

在所有的視圖文件被渲染後調用。包括元素、視圖、父視圖和佈局。 這個回調可以編輯並返回 $content 以改變將在瀏覽器中顯示的內容的渲染方式。

Helper::beforeRender($viewFile)

beforeRender 方法在控制器的 beforeRender 調用之後,但控制器實際渲染視圖和佈局之前調用。 接收被渲染的文件作爲其參數。

Helper::afterRender($viewFile)

在視圖被渲染之後但佈局被渲染之前調用。

Helper::beforeLayout($layoutFile)

在佈局被渲染之前調用。接受佈局文件名作爲其參數。

Helper::afterLayout($layoutFile)

在佈局渲染完成之後調用。接受佈局文件名作爲其參數。

內核 Helpers

緩存助手
用於通過內核緩存視圖內容。
表單助手
創建 HTML 表單及表單元素,自我構造和處理驗證問題。
Html助手
建立格式良好的標籤的簡便方法。圖片、鏈接、表格、頭標籤及其它標籤。
Javascript 助手
用於創建與各種 Javascript 庫兼容的 Javascript。
數字助手
數字和貨幣格式化。
分頁助手
模型數據分頁和排序。
RSS
輸出 RSS feed XML 數據的簡便方法。
SessionHelper
在視圖中訪問可讀的 session 值。
文本助手
漂亮的鏈接、高亮、字符智能截斷。
時間助手
接近檢測(這是明年?),漂亮的字符串格式化(今天,10:30 am)和時區轉換。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章