入門
CakePHP 框架為應用程序提供了堅實的基礎。它控制着所有方面,從用戶的初始請求直到 web 頁面的最終渲染。由於本框架遵循 MVC 原則,使得自定義和擴展應用程序變得更容易。
本框架還提供了一個基本的原始結構,從文件名到數據庫表名,保持了應用程序的一致性和邏輯性。這個概念簡單而強勁。遵循規則,就會知道東西都在哪兒,都是怎樣組織的。
體驗和學習 CakePHP 的最好辦法是坐下來做點什么。我們將開始構建一個簡單的博客系統。
博客課程
歡迎來到 CakePHP。你也許瀏覽這個課程因為你想了解 CakePHP 如何工作的更多信息。我們旨在提高生產力,使編程更愉悅:我們希望你深入代碼,以了解這一點。
本課程將引領你創建一個簡單的博客應用程序。我們獲取和安裝 CakePHP,建立和配置數據庫,並且建立列表、新建、編輯和刪除博客貼子的邏輯。
以下是我們需要的東西:
- 一個運行中的 web 服務器。假定使用的是 Apache,不過使用其它 web 服務器的說明也是類似的。我們可能要做一點服務器配置,但是大多數人完全不需要任何配置就可以運行 Cake。 請確認你擁有 PHP 5.2.8 或更高版本。
- 一個數據庫服務器。在本課程中我們將使用 MySQL 服務器。你需要了解足夠的建立數據庫的 SQL 信息:Cake 將從那得到控制權。如果我們使用 MySQL,還要確認 PHP 已經啟用了 pdo_mysql 。
- 基本的 PHP 知識。最好還懂面向對象編程:但是如果你只是個編程愛好者,也不必擔心。
- 最后,需要有一點 MVC 編程模式的基本知識。在 理解 模型 - 視圖 - 控制器 一節能找到一個快速預覽。不用擔心,大約只有半頁左右。
讓我們開始吧!
獲得 Cake
首先讓我們取得一份新鮮的 Cake 代碼的拷貝。
要得到新鮮的下載,訪問 Github 上的 CakePHP 項目: http://github.com/cakephp/cakephp/downloads 並且下載 2.0 的最新版本。
也可以使用 git 克隆代碼倉庫: git。
1 git clone git://github.com/cakephp/cakephp.git
不管是怎樣下載的,都把代碼放進 DocumentRoot 之內。一旦完成,目錄內的東西看起來應該像下面這樣:
/path_to_document_root
/app
/lib
/plugins
/vendors
.htaccess
index.php
README
現在也許是多學一點兒關於 CakePHP 目錄結構如何工作的好時候:瀏覽 CakePHP 的文件夾結構 一節。
建立博客數據庫
接着,設置博客的基本數據庫。如果你還不曾這么做,建立一個為本教程所用的空數據庫,名稱任選。現在,建立一個單表用來存儲博客貼子。我們也拋出幾個貼子用於測試。在數據庫上執行如下語句:
1 /* First, create our posts table: */ 2 CREATE TABLE posts ( 3 id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, 4 title VARCHAR(50), 5 body TEXT, 6 created DATETIME DEFAULT NULL, 7 modified DATETIME DEFAULT NULL 8 ); 9 10 /* Then insert some posts for testing: */ 11 INSERT INTO posts (title,body,created) 12 VALUES ('The title', 'This is the post body.', NOW()); 13 INSERT INTO posts (title,body,created) 14 VALUES ('A title once again', 'And the post body follows.', NOW()); 15 INSERT INTO posts (title,body,created) 16 VALUES ('Title strikes back', 'This is really exciting! Not.', NOW());
表名和列名並非隨意指定的。如果遵循 Cake 的數據庫命名規則和 Cake 類命名規則(兩者的要點都在 CakePHP 約定 一節),能夠得到額外的好處:附送的功能並且無需配置。Cake 足夠靈活以適應糟糕的遺留數據庫結構,但是遵循規則會節省很多時間。
更多的信息參見 CakePHP 約定 一節,簡單點說,只要把表命名為“posts“就能自動與 Post 模塊掛靠在一起,而 modified 和 created 列則會被 Cake 自動管理。
Cake 數據庫配置
步步高升:讓我們告訴 Cake 數據庫在哪兒以及如何連接它。對於多數情況,這是唯一的配置。
/app/Config/database.php.default 是 CakePHP 數據庫配置文件的一個副本,在同一目錄中復制這個文件,命名為database.php 。
這個配置文件非常簡單:只要用實際的值替換數組 $default 的值。下面是一個完整的配置數組的示例:
1 public $default = array( 2 'datasource' => 'Database/Mysql', 3 'persistent' => false, 4 'host' => 'localhost', 5 'port' => '', 6 'login' => 'cakeBlog', 7 'password' => 'c4k3-rUl3Z', 8 'database' => 'cake_blog_tutorial', 9 'schema' => '', 10 'prefix' => '', 11 'encoding' => '' 12 );
保存了新的 database.php 文件之后,打開瀏覽器瀏覽 Cake 歡迎頁面。上面將會顯示數據庫連接文件被找到,並且已能正確地連接到數據庫。
注解
記得你需要 PDO,並且 php.ini 文件中 pdo_mysql 必須可用(enabled)。
可選的配置
另外還有三項配置。許多開發人員完成了長長的列表項,但是它們不包含在本教程中。一是定義一個自定義字符串(salt)用於安全哈希。二是定義一個自定義數字(seed)用於加密。三是允許 CakePHP 寫入它的 tmp 文件夾。
安全 salt 用來生成哈希值。編輯 /app/Config/core.php 文件的 187 行修改默認的 salt 值。什么樣的值不會有麻煩呢?長到不容易被猜到的值。
1 /** 2 * A random string used in security hashing methods. 3 */ 4 Configure::write('Security.salt', 'pl345e-P45s_7h3*S@l7!');
密碼種子用於加/解密字符串。編輯 /app/Config/core.php 的 192 行修改默認的 seed 值。什么樣的值不會有麻煩呢?長到不容易被猜到的值。
1 /** 2 * A random numeric string (digits only) used to encrypt/decrypt strings. 3 */ 4 Configure::write('Security.cipherSeed', '7485712659625147843639846751');
最后一項任務是使 app/tmp 目錄允許 web 寫入。最好的辦法是先用(<?php echo `whoami`; ?>)找出運行 web 服務器的用戶,然后將 app/tmp 的所有者指向該用戶。在 *nix 系統中運行類似下面的命令:
1 $ chown -R www-data app/tmp
如果囿於某些條件而不能寫入這個文件夾,你會收到一個不能使用產品模式的警告。
mod_rewrite 說明
偶爾有用戶會遇到 mod_rewrite 方面的問題,所以我們在這做個簡要說明。如果 CakePHP 歡迎頁面有點兒可笑(沒有圖片或 CSS 樣式),意味着系統中缺少 mod_rewrite 功能。有一些對正確運行有幫助的提示: :
確定 .htaccess 覆蓋是被允許的:在 httpd.conf 中每個目錄有一個節定義這條規則。確認是在正確的目錄中把AllowOverride 設置 All。出於安全和執行方面的原因,不要在 <Directory /> 中把 AllowOverride 設置為All。替代方案是尋找指向所用 web 站點目錄的 <Directory> 塊。
-
確定 .htaccess 覆蓋是被允許的:在 httpd.conf 中每個目錄有一個節定義這條規則。確認是在正確的目錄中把AllowOverride 設置 All。出於安全和執行方面的原因,不要在 <Directory /> 中把 AllowOverride 設置為All。替代方案是尋找指向所用 web 站點目錄的 <Directory> 塊。
-
確認編輯了正確的 httpd.conf,而不是某個用戶或特別站點的 httpd.conf。
-
有些情況下,可能拿到的是一個不帶 .htaccess 文件的 CakePHP 副本。出現這種情況的原因是由於一些操作系統隱藏(不顯示)以 . 開頭的文件,以致拷貝時沒有拷貝這個文件。確保 CakePHP 的副本來自下載一節的站點或 git 倉庫。
-
確認 Apache 正確的加載了 mod_rewrite。應該可以在 httpd.conf 中看到如下的內容::
1 LoadModule rewrite_module libexec/httpd/mod_rewrite.so
或者(在 Apache 1.3)中
1 AddModule mod_rewrite.c
如果不想或不能讓運行中的系統使用 mod_rewrite(及其它兼容模塊),需要使用 CakePHP 內置的漂亮 URLs。取消/app/Config/core.php 文件中如下一行的注釋:
1 Configure::write('App.baseUrl', env('SCRIPT_NAME'));
同時刪除這幾個 .htaccess 文件:
/.htaccess /app/.htaccess /app/webroot/.htaccess
這會用類似 www.example.com/index.php/controllername/actionname/param 的 URL 代替 www.example.com/controllername/actionname/param。
如果 CakePHP 安裝在 Apache 以外的 web 服務器上,可以在 高級安裝 一節找到工作在 URL 重寫機制下的介紹。
接下來的 博客課程 —— 加入一個層,將開始第一個 CakePHP 應用程序。
博客課程 —— 加入一個層
建立 Post 模型
模型(model)類是 CakePHP 應用程序的面包和奶油。通過建立與數據庫結合的模型類,我們就有了隨后放置所需的顯示、添加、編輯和刪除操作的基礎。
CakePHP 的模型類放在 /app/Model 文件夾,我們建立的文件將被存為 /app/Model/Post.php。完整的文件類似於:
1 class Post extends AppModel { 2 }
在 CakePHP 中命名規則非常重要。通過把類命名為 Post,CakePHP 會自動認定這個模型將被用在 PostsController 中,而且會與名為 posts 的數據庫表關聯。.
注解
如果 CakePHP 不能在 /app/Model 文件夾內找到相對應的文件,它會動態地建立一個模型對象。也就是說,如果不慎寫錯了文件名(例如 post.php 或者 posts.php),CakePHP 就不認識所有的設置並使用默認的設置代替它。
關於模型的更多信息,諸如表前綴、回調和數據校驗,請參閱手冊中 模型 一章。
建立 Posts 控制器
接着我們為貼子建立一個控制器。這個控制器是發生貼子交互的地方。簡單地說,它就是完成運行模型和獲得貼子相關工作的地方。我們將在 /app/Controller 目錄的 PostsController.php 文件中放置一個控制器類。類的基本內容類似於:
1 class PostsController extends AppController { 2 public $helpers = array('Html', 'Form'); 3 }
現在在控制器中添加一個動作。控制器中的動作通常實現單一的功能或接口。例如,當用戶請求http://www.example.com/post/index(這個和 http://www.example.com/post 相同),他們可能期待看見一個貼子列表。這個動作的代碼類似於:
1 class PostsController extends AppController { 2 public $helpers = array('Html', 'Form'); 3 4 public function index() { 5 $this->set('posts', $this->Post->find('all')); 6 } 7 }
我來解釋一下這個動作。通過在 PostsController 中定義一個函數 index(),用戶現在就能夠通過向www.example.com/posts/index 提交訪問程序邏輯。類似地,如果定義一個函數叫 foobar(),用戶就能夠訪問 www.example.com/posts/index。
警告
以短小的方式命名控制器和動作是一種誘惑,要抑制這種誘惑。遵循 CakePHP 的命名規則(以復數命名控制器等)建立易讀、易理解的動作名稱。隨后可以通過``路由``映射 URLs 到代碼。
上例中index動作中使用 set() 方法從控制器向視圖(后面會創建)傳遞數據。設置視圖那一行中名為 ‘posts’ 的變量等於 Post 模型的 find('all') 方法的返回值。由於遵循了 Cake 的命名規則,Posts 模型自動可用($this->Post)。
要學習 Cake 控制器的更多內容,請瀏覽 控制器 一章。
建立 Post 視圖
現在已經有了數據流、模型、程序邏輯和定義數據流向的控制器。我們要建立與上面例子中的 index 動作對應的視圖。
Cake 視圖僅是呈現應用程序布局的片段。對於多數應用程序,視圖是混合了 PHP 的 HTML,但是它也可以是 XML、CSV,甚至是二進制數據。
布局是包裝視圖的處理顯示的代碼,能夠定義和切換,但是現在,我們使用默認的布局。
還記得上一節是如何使用 set() 方法給視圖中的 ‘posts’ 變量賦值的嗎?所傳遞的數據類似於:
1 // print_r($posts) output: 2 3 Array 4 ( 5 [0] => Array 6 ( 7 [Post] => Array 8 ( 9 [id] => 1 10 [title] => The title 11 [body] => This is the post body. 12 [created] => 2008-02-13 18:34:55 13 [modified] => 14 ) 15 ) 16 [1] => Array 17 ( 18 [Post] => Array 19 ( 20 [id] => 2 21 [title] => A title once again 22 [body] => And the post body follows. 23 [created] => 2008-02-13 18:34:56 24 [modified] => 25 ) 26 ) 27 [2] => Array 28 ( 29 [Post] => Array 30 ( 31 [id] => 3 32 [title] => Title strikes back 33 [body] => This is really exciting! Not. 34 [created] => 2008-02-13 18:34:57 35 [modified] => 36 ) 37 ) 38 )
Cake 的視圖文件存儲在 /app/View 目錄下與控制器名稱(去掉了 controller 后綴)同名的文件夾中(現在的情況下,要創建 /app/View/Posts 文件夾)。使用漂亮的表格格式化數據,其視圖類似於:
1 <!-- File: /app/View/Posts/index.ctp --> 2 3 <h1>Blog posts</h1> 4 <table> 5 <tr> 6 <th>Id</th> 7 <th>Title</th> 8 <th>Created</th> 9 </tr> 10 11 <!-- Here is where we loop through our $posts array, printing out post info --> 12 13 <?php foreach ($posts as $post): ?> 14 <tr> 15 <td><?php echo $post['Post']['id']; ?></td> 16 <td> 17 <?php echo $this->Html->link($post['Post']['title'], 18 array('controller' => 'posts', 'action' => 'view', $post['Post']['id'])); ?> 19 </td> 20 <td><?php echo $post['Post']['created']; ?></td> 21 </tr> 22 <?php endforeach; ?> 23 <?php unset($post); ?> 24 </table>
希望這看起來挺簡單。
你可能已經注意到例子中所用的那個調用 $this->HTML 的對象,這是 CakePHP 中 ‘HtmlHelper’ 的一個實例。CakePHP 帶有一個生成類似鏈接、表單輸出、JavaScript 和 Ajax 快照的視圖助手集合。在 助手 一節你能學到更多如何使用它們的方法,現在要重點注意的是 link() 方法,它能用給定的標題(第一個參數)和 URL (第二個參數)生成 HTML 鏈接。
推薦使用數組格式在 CakePHP 中指定 URLs。在“路由”一節對此有更多的解釋。使用數組格式處理 URLs 可以獲得 CakePHP 服務器的路由兼容性。也可以用 /controller/action/param1/param2 的格式將 URLs 關聯到應用程序。
現在,讓你的瀏覽器指向 http://www.example.com/posts/index 。你會看到帶有標題和帖子列表的格式正確的視圖。
如果你點擊了我們建立的這個視圖中的某個鏈接(它將一個帖子標題鏈接到 URL /posts/view/some_id), 你應該會發現 CakePHP 會報告那個 action 還沒有定義。 如果你沒有收到這個報告,表明有些事情可能出錯了,或者你竟然已經定義了它,這是很詭異的一種情形^_^。 現在,讓我們在 PostsController 中建立它:
1 class PostsController extends AppController { 2 public $helpers = array('Html', 'Form'); 3 4 public function index() { 5 $this->set('posts', $this->Post->find('all')); 6 } 7 8 public function view($id = null) { 9 $this->Post->id = $id; 10 $this->set('post', $this->Post->read()); 11 } 12 }
set() 調用看上去有點眼熟。需要注意的是,我們在此優先使用 read() 而不是 find('all'),這是因為我們僅僅要得到一條帖子信息。
還要注意,我們的視圖 action 獲取了一個參數: 我們希望看到的帖子的 ID。 這個參數是通過 URL 請求傳遞給 action 的。 如果用戶請求 /posts/view/3,那么值 ‘3’ 就被傳遞給 $id。
現在讓我們建立一個新的 ‘view’ action 放在 /app/View/Posts/view.ctp 文件中。
1 <!-- File: /app/View/Posts/view.ctp --> 2 3 <h1><?php echo h($post['Post']['title']); ?></h1> 4 5 <p><small>Created: <?php echo $post['Post']['created']; ?></small></p> 6 7 <p><?php echo h($post['Post']['body']); ?></p>
嘗試輸入鏈接 /posts/index 或者手動訪問 /posts/view/1,看看工作是否正常。.
添加帖子
雖然從數據庫中讀出貼子並展示給我們是個不錯的開始,但是我們還需要可以添加貼子。
首先,從在 PostsController 中建立 add() 方法開始:
1 class PostsController extends AppController { 2 public $helpers = array('Html', 'Form', 'Session'); 3 public $components = array('Session'); 4 5 public function index() { 6 $this->set('posts', $this->Post->find('all')); 7 } 8 9 public function view($id) { 10 $this->Post->id = $id; 11 $this->set('post', $this->Post->read()); 12 13 } 14 15 public function add() { 16 if ($this->request->is('post')) { 17 $this->Post->create(); 18 if ($this->Post->save($this->request->data)) { 19 $this->Session->setFlash('Your post has been saved.'); 20 $this->redirect(array('action' => 'index')); 21 } else { 22 $this->Session->setFlash('Unable to add your post.'); 23 } 24 } 25 } 26 }
注解
在使用 Session 的任何一個 controller 中都需要包含 SessionComponent (和SessionHelper)。如果需要,可以將它包含在 AppController 中。
add() 實現了這樣幾個功能:如果表單提交的數據非空,就試圖使用 Post 模型保存數據。如果因為某些原因保存未成功,則渲染視圖,這給了我們向用戶顯示數據校驗或其它警告的機會。
每個 CakePHP 請求包含一個 CakeRequest 對象,它可以通過 $this->request 訪問。 request 對象包含這次請求被獲取的信息,並能夠用於應用程序流的控制。 在本例中,我們使用 CakeRequest::is() 方法檢驗請求是否是以 HTTP POST 格式提交的。
當用戶使用表單向應用程序提交數據(POST),其信息可以使用 $this->request->data 獲取。 可以使用 pr() 或debug() 方法輸出這些數據。
我們使用了 Session 組件的 SessionComponent::setFlash() 方法發送了一條信息給 session 變量,用於在中轉頁上顯示。 在中轉頁的布局中我們用 SessionHelper::flash 顯示和清除這個 session 變量。 該控制器的Controller::redirect 方法用於跳轉到其它 URL。 參數 array('action' => 'index') 指定了跳轉到 /posts URL,等於 posts 控制器的 index 方法。 你可以參考 API 中的 Router::url() 功能,它使你可以指定為不同的 Cake 函數指定一個 URL 格式。
調用 save() 方法將檢查檢驗錯誤,並在出現錯誤時跳過保存。 我們將在后續的章節中討論如何處理這些錯誤。
數據校驗
Cake 在獲取表單校驗的單調輸出方面做了大量的工作。每個人都痛恨無止境的編寫表單及其驗證。CakePHP 使其變得更快更容易。
想要更好的利用校驗功能,就需要在視圖中使用 FormHelper 助手。FormHelper 助手默認在所有視圖中都可用,用法是 $this->Form。
這是我們添加的視圖:
1 <!-- File: /app/View/Posts/add.ctp --> 2 3 <h1>Add Post</h1> 4 <?php 5 echo $this->Form->create('Post'); 6 echo $this->Form->input('title'); 7 echo $this->Form->input('body', array('rows' => '3')); 8 echo $this->Form->end('Save Post'); 9 ?>
在這里,我們用 FormHelper 助手生成一個 HTML 表單的起始標簽。$this->Form->create() 生成的 HTML 是:
1 <form id="PostAddForm" method="post" action="/posts/add">
如果 create() 是不帶參數調用的,表示創建的表單將以 POST 形式提交給同一個控制器的 add() (或者當表單中含有 id 元素時提交給 edit())動作。
$this->Form->input() 方法用來生成同名的表單元素,這個方法的第一個參數告訴 CakePHP 前后台通訊的是哪個域,第二個參數允許指定選項:本例中,是 textarea 域的行數。這里有一點自動完成的:input() 方法將基於 model 指定的域生成不同的表單元素。
$this->Form->end() 調用生成一個 submit 元素並結束表單。如果提供給 end() 方法的第一個參數是字符串,FormHelper 生成一個相應名稱的 submit 域並關閉表單標簽。再說一次, 助手 一節有更多的助手信息。
現在我們返回並更新 /app/View/Posts/index.ctp 視圖使其包含一個新的 “Add Post” 鏈接。在 <table> 之前添加如下行:
1 <?php echo $this->Html->link( 2 'Add Post', 3 array('controller' => 'posts', 'action' => 'add') 4 ); ?>
你可能會奇怪:我如何通知 Cake 我的校驗要求?校驗規則是定義在模型中的。讓我們回顧 Post 模型並稍作調整:
1 class Post extends AppModel { 2 public $validate = array( 3 'title' => array( 4 'rule' => 'notEmpty' 5 ), 6 'body' => array( 7 'rule' => 'notEmpty' 8 ) 9 ); 10 }
$validate 數組告訴 CakePHP 在 save() 方法被調用時如何校驗我們的數據。這里,我指定 title 和 body 都不能為空。CakePHP 的校驗功能很強勁,帶有一批預置的規則(如 信用卡號碼、Email 地址等),而且可以靈活地添加自己的校驗規則。可以瀏覽 數據校驗 獲取更多的相關信息。
現在已經有了校驗規則,試着輸入空的 title 和 body,看看它們是如何工作的。當我們使用 FormHelper 的FormHelper::input() 方法創建表單,校驗的錯誤信息會自動顯示。
編輯帖子
我們已經來到了帖子編輯這一步,現在你已經是一個 CakePHP 的高手了,所以你應該操起一個模式。編寫動作,然后是視圖。PostsController 的 edit() 方法類似於:
1 public function edit($id = null) { 2 $this->Post->id = $id; 3 if ($this->request->is('get')) { 4 $this->request->data = $this->Post->read(); 5 } else { 6 if ($this->Post->save($this->request->data)) { 7 $this->Session->setFlash('Your post has been updated.'); 8 $this->redirect(array('action' => 'index')); 9 } else { 10 $this->Session->setFlash('Unable to update your post.'); 11 } 12 } 13 }
這個動作首先檢查用戶提交的是不是 GET 請求。如果是,就找到 Post 並將其傳遞給視圖。如果不是,就可能包含 POST 數據。我們將使用 POST 數據更新貼子記錄,或者將校驗的錯誤信息踢回並顯示給用戶。
edit 視圖類似於:
1 <!-- File: /app/View/Posts/edit.ctp --> 2 3 <h1>Edit Post</h1> 4 <?php 5 echo $this->Form->create('Post', array('action' => 'edit')); 6 echo $this->Form->input('title'); 7 echo $this->Form->input('body', array('rows' => '3')); 8 echo $this->Form->input('id', array('type' => 'hidden')); 9 echo $this->Form->end('Save Post');
這個視圖輸出編輯表單(帶有相應數據值),所有的錯誤校驗信息也一並提供。
有件事需要注意:如果提供的數據數組中包含 ‘id’ 域,CakePHP 認為這是要修改一個模型的數據。如果沒有 ‘id’ 域,cake 會認為當 save() 方法被調用時插入一條新的模型數據(參見 add 視圖)。
現在可以更新 index 視圖,添加一個用於編輯的鏈接:
1 <!-- File: /app/View/Posts/index.ctp (edit links added) --> 2 3 <h1>Blog posts</h1> 4 <p><?php echo $this->Html->link("Add Post", array('action' => 'add')); ?></p> 5 <table> 6 <tr> 7 <th>Id</th> 8 <th>Title</th> 9 <th>Action</th> 10 <th>Created</th> 11 </tr> 12 13 <!-- Here's where we loop through our $posts array, printing out post info --> 14 15 <?php foreach ($posts as $post): ?> 16 <tr> 17 <td><?php echo $post['Post']['id']; ?></td> 18 <td> 19 <?php echo $this->Html->link($post['Post']['title'], array('action' => 'view', $post['Post']['id'])); ?> 20 </td> 21 <td> 22 <?php echo $this->Html->link('Edit', array('action' => 'edit', $post['Post']['id'])); ?> 23 </td> 24 <td> 25 <?php echo $post['Post']['created']; ?> 26 </td> 27 </tr> 28 <?php endforeach; ?> 29 30 </table>
刪除帖子
下面我們來看刪除貼子的道道。在 PostsController 中添加 delete() 動作:
1 public function delete($id) { 2 if ($this->request->is('get')) { 3 throw new MethodNotAllowedException(); 4 } 5 if ($this->Post->delete($id)) { 6 $this->Session->setFlash('The post with id: ' . $id . ' has been deleted.'); 7 $this->redirect(array('action' => 'index')); 8 } 9 }
這個邏輯根據 $id 刪除指定的貼子,並且使用 $this->Session->setFlash() 在用戶重定向到 /posts 之后顯示一條確認信息。如果用戶試圖用 GET 請求執行刪除,我們就拋出一個異常。我們沒有捕獲的異常,將被 CakePHP 的異常句柄捕獲並顯示一個友好的錯誤頁。有許多內置的 異常 ,能夠用於指示應用程序需要生成的不同的 HTTP 錯誤。
因為我們僅僅執行了一些邏輯就重定向了,這個動作沒有視圖。但是仍然可能需要更新 index 視圖,添加允許用戶刪除貼子的鏈接:
1 <!-- File: /app/View/Posts/index.ctp --> 2 3 <h1>Blog posts</h1> 4 <p><?php echo $this->Html->link('Add Post', array('action' => 'add')); ?></p> 5 <table> 6 <tr> 7 <th>Id</th> 8 <th>Title</th> 9 <th>Actions</th> 10 <th>Created</th> 11 </tr> 12 13 <!-- Here's where we loop through our $posts array, printing out post info --> 14 15 <?php foreach ($posts as $post): ?> 16 <tr> 17 <td><?php echo $post['Post']['id']; ?></td> 18 <td> 19 <?php echo $this->Html->link($post['Post']['title'], array('action' => 'view', $post['Post']['id'])); ?> 20 </td> 21 <td> 22 <?php echo $this->Form->postLink( 23 'Delete', 24 array('action' => 'delete', $post['Post']['id']), 25 array('confirm' => 'Are you sure?')); 26 ?> 27 <?php echo $this->Html->link('Edit', array('action' => 'edit', $post['Post']['id'])); ?> 28 </td> 29 <td> 30 <?php echo $post['Post']['created']; ?> 31 </td> 32 </tr> 33 <?php endforeach; ?> 34 35 </table>
使用 postLink() 生成用 JavaScript 調用刪除貼子請求的鏈接。允許使用 GET 請求刪除貼子是非常危險的,web 爬蟲可能會意外地刪除全部內容。
注解
這個視圖的代碼也在刪除之前使用 FormHelper 的 JavaScript 對話框提醒用戶。
路由
多數情況下,CakePHP 的默認路由都能夠很好地工作。對用戶體驗和搜索引擎兼容敏感的程序員將注意到 CakePHP 的 URL 映射到動作的方式。所以在這篇教程里我們僅僅快速的更改了一下路由。
路由技術的更多更高級的信息,請參見 路由配置 。
默認的,CakePHP 用 PagesController 回應對站點根的訪問(例如 www.example.com),渲染一個叫 “home” 的視圖。我們通過建立一條路由規則,用我們自己的 PostsController 來代替它。
可以在 /app/Config/routes.php 中找到路由配置。要注釋掉或者刪除定義默認路由的那一行。它看起來像是:
1 Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home'));
一行將默認的 home 頁關聯給 URL ‘/’。我們想要用我們自己的控制器關聯它,所以用如下行替換這一行:
1 Router::connect('/', array('controller' => 'posts', 'action' => 'index'));
這將把 PostsController 的 index() 動作關聯給 URL ‘/’。
注解
CakePHP 還支持 ‘逆向路由’ ——如果通過``array(‘controller’ => ‘posts’, ‘action’ => ‘index’)`` 傳遞給期望得到數組的函數來定義如上路由,那么結果將是 ‘/’。這意味着總是用數組通過路由去定義要去的 URL 是個好主意,並能確保總是會指向同一個位置。
結語
創建應用程序這條路,將使你贏得超出以往的狂熱幻想的和平、光榮、愛和金錢。容易,不容易?記住,這個教程只是一個基礎。CakePHP 提供了更多的特性和更靈活的方式,簡單起見,我們不希望這個教程覆蓋那么多。使用手冊的剩余部分作為構建富於特性的應用的指南。
現在已經建立了一個基於真實內容的基本的 Cake 應用程序。閱讀 Cookbook 和 API 的剩余內容,開始自己的項目吧。
如果需要幫助,到 #cakephp 來看我們。歡迎來到 CakePHP!
建議后續閱讀:
這些都是學習CakePHP的人將來通常要研究的共同任務:
- 布局: 自定義 web 站點的布局
- 元素 :包含和重用視圖片斷
- 腳手架: 創建代碼前的原型
- 使用 Bake 生成代碼 使用 Bake 生成基本的 CRUD 代碼
- 簡單授權驗證和授權應用程序: 用戶驗證和授權教程
延伸閱讀
- 一個典型的 CakePHP 請求
- CakePHP 約定
- 控制器約定
- 關於控制器命名的思考
- 文件名和類名約定
- 模型和數據庫約定
- 視圖約定
- 控制器約定
- CakePHP 的文件夾結構
- app 文件夾
- CakePHP 的結構
- 應用程序擴展
- 控制器擴展 (“組件”)
- 模型擴展 (“行為”)
- 視圖擴展 (“助手”)