2008年3月26日 星期三

CakePHP 1.2 Model 資料驗証 (Data Validation) 簡介

Data Validation 是 Model 中最重要的功能,也是最重要的程式區塊。當要對資料庫進行Insert, Update時,都會執行這個區塊要設定來檢查資料是否正確。一般而言,寫網站程式會在對資料庫存取(不管是select, insert, update)都會先對資料做初步的檢查(例如:不能是空或空白字串;一定要數字;符合某種格式 - regex 檢查)。CakePHP在方面的設計,比1.1增強許多,在1.1的版本,只有Regex檢查,到了1.2可以針對單一個欄位做多種規則的檢查,也可以自訂函式來做驗証。CakePHP內建的規則可以查 your_cakephp1.2/cake/libs/validation.php

CakePHP的資料驗証設定很彈性,因此在設定上的寫法花樣很多,以下只例舉我常用的做法:

public $validate = array(
"account" => array(
/* 檢查是不是數字與英文字母的組合 */
"alphanumberic" => array(
"rule" => "alphaNumeric",
"message" => "只能是數字或英文字母",
"last" => true
), /* end alpha-numeric */
/* 檢查字串的長度在4~20之間 */
"length" => array(
"rule" => array("between", 4, 20),
"message" => "您的帳號長度不正確,只能 4~20字元",
"last" => true
), /* end length */
/* 檢查是不是唯一值 (自訂函式) */
"unique" => array(
"rule" => array("checkUnique", "account"),
"message" => "這個帳號已經註冊,請重新取一個",
"on" => "create"
) /* end unique */
),/* end for account */

}

資料驗証的使用方式是 "自訂的規則名稱" => array("rule" => "內建或自訂的規則", "message"=>"發生錯誤時,要顯示的訊息"),其中 "rule" => "內建或自訂的規則" ,如果使用的規則是Regex或者沒有額外參數的函式(像alphaNumeric,只要傳值去做驗証即可,不需要其他額外的參數),那就可以以字串的方式設定。相反的,如果規則是函式,且需要額外的參數時(像 between, 需要有最大、最小值),那就要以array的方式設定。

以下是其他參數的說明:

on: 值有"create"和"update",如果值是"create",意思是指在做insert時,才會使用這個驗証規則,同理是"update"時,只有在update資料庫時,才會使用。如果都不做設定的話,不論是要做insert或update,只要Controller有把這個欄位的值傳進來,就會使用這個規則做驗証。

last: 設定成 true 時(CakePHP預設值是false),是告知CakePHP只要這個規則沒通過時,就不要再執行同欄位的其他規則。

自訂函式說明:

以下是程式碼是截自CakePHP官網的說明,請見 http://book.cakephp.org/view/125/data-validation

function checkUnique($data, $fieldName) {
$valid = false;
if(isset($fieldName) && $this->hasField($fieldName))
{
$valid = $this->isUnique(array($fieldName => $data));
}
return $valid;
}

在寫自訂的函式時,請注意,第一個參數要保留給CakePHP把欄位的值傳進來,從第二個參數開始才是自訂的參數。像上面的checkUnique,$data是指傳進來的欄位值,$fieldName是指要檢查的欄位名稱。

參考資料:

http://book.cakephp.org/view/125/data-validation

CakePHP 1.2 Controller 簡介

依據MVC的概念,Controller通常都是負責網站規則、流程的控管,CakePHP也不例外。在程式的安排上,CakePHP建議一個Controller負責一個Model相關的網站規則與流程,簡單來說,在寫Controller時,如果沒特別的需求,一個Controller最好只使用一個Model;一來網站的程式好管理,二來Controller的程式在執行過程也減少記憶體的浪費。因此在寫網站時,可以依據這個法測,來安排規劃程式。Controller的method通常稱作Action,而每個Action,如果沒有特殊需求,通常會有專屬的View。Controller通常是繼承CakePHP的AppController (your_cake1.2/cake/libs/controller/app_controller.php),從source code來看,其實Controller也可以直接繼承 Controller(your_cake1.2/cake/libs/controller/controller.php),視需要而定。

Controller 屬性:
$name: 顧名思義,也就是Controller的名稱,但要注意的是,不是Controller的ClassName。例如:PostController (檔名:post_controller.php),那它的 $name 應該是 Post 而不是 PostController;而且$name這個變數,在CakePHP的設計中,如果Controller程式沒有修改使用那些Model的話,它預設會去找相同名稱的Model,也就是Post這個Model。

$uses: 設定使用那些Model,如果都沒使用Model時,可以設定成 null,如果在程式中,沒有修改這個值的話,則CakePHP會去尋找和Controller相同名稱的Model。要使用model時,以array的方式來設定。Ex: public $uses = array('Post');

$components: 在CakePHP的設計中,components是指協助Controller處理網站規則與流程。如網站常用會用到的Session, Cookie等,CakePHP本身也內建了相對應的component來協助處理。如果要使用component的話,以array的方式來設定即可。Ex: public $uses = array('Session', 'Cookie');

$helpers: 在CakePHP的設計中,components是指協助處理版型的,也就是View。如果沒有設定時,Controller會預設使用 Html 及 Form 這兩個Helper。同理,如果要使用其他的Helper時,以array的方式設定。Ex: public $helpers = array('Form', 'Ajax');

$layout: 指定Controller要使用那個外框的版型,預設是 default.ctp (your_cake1.2/app/views/layouts/defautl.ctp or your_cake1.2/cake/libs/view/layouts/default.ctp)。可以在Controller或者Action中,重新設定這個值,來使用不同的外框版型。Ex: $this->layout='ajax'; /* 會使用 layouts/ajax.ctp */

$pageTitle: 設定版型中 HTML的Title。使用的前題是,在外框的版型上,要保留 <?php echo $title_for_layout; ?> (請參考 CakePHP 1.2 第一個程式,換掉CakePHP說明首頁 )。

參數屬性:
$this->data: 在CakePHP的設計上,如果你的版型上,是寫
<input name="data[User][first_name]" value="" type="text" /> 且用POST傳給Controller時,那麼在Controller的Action中,就可以使用 $this->data['User']['first_name'] 來讀取這個值。(註:只有 POST 才行)。

Controller常用的函式:

set(string $var, mixed $value): 這個函式最常用,主要是要把資料,傳給View使用。

redirect(string $url, integer $status, boolean $exit): 轉址,類似 header('Location: /help.html'); 功能。

flash(string $message, string $url, integer $pause): 跳轉畫面。會先出現一段訊息後,再自動跳轉到指定的網址。

Callbacks:
beforeFilter(): 在呼叫任何Action之前,會先執行這個函式。

beforeRender(): 在產生View的結果前,會先執行這個函式。

afterFilter(): 在呼叫任何Action之後,會再執行這個函式。

afterRender(): 在產生View的結果之後,會再執行這個函式。

詳細的執行順序,請見 CakePHP處理HTTP Request 典型的流程

其他常用的函式:
loadModel('ModelName'): 自行載入要使用的Model。

disableCache(): 告知瀏覽器不要cache 網頁。

paginate(): 分頁的功能,請見 CakePHP Pagination (分頁功能) , CakePHP Pagination (分頁功能) 加入自己的參數

requestAction(string $url, array $options): 顧名思意,就是呼叫其他Controller的Action。如果需要被呼叫的Action的版型,請在options加'return'Ex: echo $this->requestAction('/post/all', array('return')); 如此就可以在網頁上顯示這個Action的結果。同理,不需要版型的話,就不要傳入'return'。這個函式可以應用的地方很多,也可以在View裏面使用(例如在某個action的.ctp用使用),簡單來說,可以視作一種呼叫函式的方法。

參考資料:http://book.cakephp.org/view/49/controllers



2008年3月25日 星期二

Open SSL 的 NO OPENSSL_Applink 錯誤

最近要寫一個透過Gmail來寄信的小程式,因為gmail的SMTP是有加SSL的,自然要找上Open SSL 這個好用的Open Source來做。

我用的環境是Windows XP + Vistual Studio 2005,在使用的過程中,可能有的人會發生 No OPEN_SSL_AppLink 的錯誤,在OpenSSL的FAQ中,有特別提到這個會錯誤發生的原因,主要是在編譯Open SSL時,預設的參數是 /MD (MultiThread DDL),而像我用的WTL + Vistual C++ 8,預設的編譯環境是 /MTD (MultiThread Debug),兩者編譯的環境不同,就會發生這個錯誤。

要解決這個問題,FAQ說要改成相同的編譯環境即可,我是要維持MTD的環境,所以只好去改OpenSSL產生的make檔(nt.mak),把/MD這個參數改成 /MTD。

如果有相同問題的人,可以試看看。

如何使用IWebBrowser2 加入自定的Header - MFC

相信很多人都曾有過在自己的視窗程式中,鉗入一個IE元件,也就是IWebBrowser2這個Interface,最近我也在寫類似的功能,這次要在HTTP的Header中,加入自訂的設定與資訊;在google找到的範例中,對於GET是可行的,也已經解決一半的問題,但是在遇到需要用POST時,會發現這些範例,不論怎麼傳,都還是GET的方式。
加入自訂的Header方式,主要是利用BeforeNavigate2這個Event。如果是用MFC來實作的話,你會有一個類似
BeforeNavigate2Explorer1(LPDISPATCH pDisp, VARIANT* URL, VARIANT* Flags, VARIANT* TargetFrameName, VARIANT* PostData, VARIANT* Headers, BOOL* Cancel) 這個函數。
首先在這個Event中,把Cancel設成TRUE (*Cancel = TRUE),然後再這個函數中,再呼叫一次Navigate2,並傳入自訂的header。
以下是我的方式。(請不要照抄,因為只是說明,並不是可以執行的程式)
void CMyDlg::BeforeNavigate2Explorer1(LPDISPATCH pDisp, VARIANT* URL, VARIANT* Flags, VARIANT* TargetFrameName, VARIANT* PostData, VARIANT* Headers, BOOL* Cancel)
{
// 用來判斷是不是自己發出的Navigate2,一開始m_bIsReNavigate是FALSE!
this->m_bIsReNavigate = !this->m_bIsReNavigate;

if(this->m_bIsReNavigate) {
*Cancel = TRUE;
_variant_t header;
// 加入自己的Header ex: AAA:BBBrn
header.SetString(my_header_string);

_variant_t p;
_variant_t e(VT_EMPTY);
// Copy使用者傳的POST資料,請用VariantCopyInd,不要用VariantCopy;因為PostData有safearray,如果用VariantCopy,並不會把array複製進來。
VariantCopyInd(&p, PostData);
// 重新再Request一次
this->m_browser.Navigate2(URL, &e, &e, &p, &header);
}// if(this->m_bIsReNavigate)
}

CakePHP Pagination (分頁功能) 加入自己的參數

如果還不知道什麼是 Pagination 或者還不了解如何使用,請參考: CakePHP Pagination (分頁功能)

通常在管理後台實作時,常設定許多查詢條件來查詢資料,比如:起始、結束時間。通常這些參數都是用GET的方式在傳遞。以下的範例程式,主要說明如何把GET的參數,融入CakePHP的分頁功能裏面。

Controller:post_controller.php

class PostController extends AppController {
public $name = 'Post';
public $uses = null;

function all() {
// 分頁設定
$this->paginate = array(
'fields' => array('Article.id', 'Article.title', 'Article.created'),
'limit' => 3,
'order' => 'Article.created desc',
);

/* 如果有自訂的GET參數,取得到,加到 Controller 的 passedArgs */
$tmp = '';

if(isset($_GET['a']) && ($tmp = trim($_GET['a'])) != "")
$this->passedArgs['a'] = $tmp;
if(isset($_GET['b']) && ($tmp = trim($_GET['b'])) != "")
$this->passedArgs['b'] = $tmp;

$this->loadModel("Article");
/*
$this->Article->recursive = false;*/

$this->Article->recursive = 0;

$this->set('articles', $this->paginate($this->Article,"Article.user_id='".$this->UserID."'"));

}// all

}// enc Post
?>

View: all.ctp

<?php
$args = $this->passedArgs;
unset($args['page']); /* 記得要去除 page 參數,否則 CakePHP 會當成一般的參數處理,屆時連結會多出很多page參數 */
// 把額外的參數傳給分頁模組
$paginator->options(
array('url'=>$args));
$th = array($paginator->sort("標題", "title"), $paginator->sort("建立時間", "created"), "操作");
echo $html->tableHeaders($th);

$size = count($articles);
for($i = 0; $i < $size; $i++) {
$tr = array($articles[$i]["Article"]["title"], $articles[$i]["Article"]["created"], "<a href='/post/edit/".$articles[$i]["Article"]["id"]."'>編輯</a>");
echo $html->tableCells($tr, array("bgcolor"=>"#999999"), array("bgcolor"=>"white"));

}// end for
?>
</table>
<center>
<?php
echo $paginator->first('第一頁'). ' ';
echo $paginator->prev('<< 前一頁').' ';
echo $paginator->numbers(array('separator'=>' - '));
echo ' '.$paginator->next('下一頁 >>');
echo ' '.$paginator->last("最後一頁");
?>
<br>
<?php
echo $paginator->counter(array(
'format' => '目前在第 %page% 頁 / 總共 %pages% 頁, 每頁 %current% 筆資料, 總共 %count% 筆, 目前是第 %start% 至 %end% 筆資料'
));
?>
</center>

HTML

<table border='1' bordercolor='#cccccc' cellspacing='0' cellpadding='5' width='80%' align='center'>
<tr><th><a href="/post/all/3/page:2/a:c/b:d/sort:title/direction:desc">標題</a></th>

<th><a href="/post/all/3/page:2/a:c/b:d/sort:created/direction:asc">建立時間</a></th>

<th>操作</th>

</tr>

<tr bgcolor="#999999>資料顯示在這裏(略)</tr></table>
<center>
<span><a href="/post/all/3/page:1/a:c/b:d/sort:title/direction:asc">第一頁</a></span> <a href="/post/all/3/page:1/a:c/b:d/sort:title/direction:asc">&lt;&lt; 前一頁</a> <span><a href="/post/all/3/page:1/a:c/b:d/sort:title/direction:asc">1</a></span> - <span class="current">2</span> - <span><a href="/post/all/3/page:3/a:c/b:d/sort:title/direction:asc">3</a></span> - <span><a href="/post/all/3/page:4/a:c/b:d/sort:title/direction:asc">4</a></span> <a href="/post/all/3/page:3/a:c/b:d/sort:title/direction:asc">下一頁 &gt;&gt;</a> <span><a href="/post/all/3/page:4/a:c/b:d/sort:title/direction:asc">最後一頁</a></span><br>
目前在第 2 頁 / 總共 4 頁, 每頁 3 筆資料, 總共 12 筆, 目前是第 4 至 6 筆資料</center>

由上面,可以看到自訂的參數也是以 /參數名稱:參數值 的方式,加到連結裏面。同理,在controller 中,可以透過passedArgs取得以/參數名稱:參數值的數值。

CakePHP Pagination (分頁功能)

原本 1.1 版本是沒有分頁功能,但可以藉由 Bakery 上的討論區找到寫好的 Component 和 Helper。到了1.2版之後,CakePHP很貼心地內建了這項功能。在開發網站上,分頁是一項很常用的功能,有了這項功能,更可以讓開發的速度加快。

分頁的功能,官網上面已經有說明了,Bakery 上也有很多相關的說明,都可以參考。我寫了一個簡單的範例程式來說明CakePHP的pagination如何使用。

Controller:post_controller.php

class PostController extends AppController {

public $name = 'Post';
public $uses = null;

function all() {
$this->paginate = array(
'fields' => array('Article.id', 'Article.title', 'Article.created'), /* 選擇要顯示的資料庫欄位 */
'limit' => 3, /* 每頁幾筆資料 */
'order' => 'Article.created desc' /* 預設的排序方式 */
);

$this->loadModel("Article"); /* 載入 Model */
//$this->Article->recursive = false; /* 如果 Model 有 hasOne, hasMany 等對應關係,且不需要時,把 recursive 設成 false */

$this->Article->recursive = 0; /* 如果 Model 有 hasOne, hasMany 等對應關係,且不需要時,把 recursive 設成 0 */

$this->set('articles', $this->paginate($this->Article,"Article.user_id='".$this->UserID."'")); /* 使用 paginate 函式取得資料,第二個參數可設定條件 */
}// all

}

View: all.ctp

<table border='1' bordercolor='#cccccc' cellspacing='0' cellpadding='5' width='80%' align='center'>
<?php
$th = array($paginator->sort("標題", "title"), $paginator->sort("建立時間", "created"), "操作"); /* 在版型的標題上,加入可以針對欄位做排序的功能 */
echo $html->tableHeaders($th);

$size = count($articles);
for($i = 0; $i < $size; $i++) {
$tr = array($articles[$i]["Article"]["title"], $articles[$i]["Article"]["created"], "<a href='/post/edit/".$articles[$i]["Article"]["id"]."'>編輯</a>"); /* 顯示資料 */
echo $html->tableCells($tr, array("bgcolor"=>"#999999"), array("bgcolor"=>"white"));

}// end for
?>
</table>
<center>
<?php
echo $paginator->first('第一頁'). ' ';
echo $paginator->prev('<< 前一頁').' ';
echo $paginator->numbers(array('separator'=>' - '));
echo ' '.$paginator->next('下一頁 >>');
echo ' '.$paginator->last("最後一頁");
?>
<br>
<?php
echo $paginator->counter(array(
'format' => '目前在第 %page% 頁 / 總共 %pages% 頁, 每頁 %current% 筆資料, 總共 %count% 筆, 目前是第 %start% 至 %end% 筆資料'
));
?>
</center>

最後得到的HTML碼會是:

<table border='1' bordercolor='#cccccc' cellspacing='0' cellpadding='5' width='80%' align='center'>
<tr><th><a href="/post/all/page:1/sort:title/direction:asc">標題</a></th>

<th><a href="/post/all/page:1/sort:created/direction:desc">建立時間</a></th>

<th>操作</th>

</tr>

<tr bgcolor="#999999>資料顯示在這邊(略)</tr></table>
<center>
<span class="current">1</span> - <span><a href="/post/all/page:2">2</a></span> - <span><a href="/post/all/page:3">3</a></span> - <span><a href="/post/all/page:4">4</a></span> <a href="/post/all/page:2">下一頁 &gt;&gt;</a> <span><a href="/post/all/page:4">最後一頁</a></span><br>
目前在第 1 頁 / 總共 4 頁, 每頁 3 筆資料, 總共 12 筆, 目前是第 1 至 3 筆資料</center>

由上面的HTML可以發現CakePHP已經將分頁的功能,自動做好了,而且分頁的參數是以 /page:n 的方式產生。在標題的部分,也做好排序的功能,可以試著點選看看,會自動做遞增、遞減的排序。

參考資料:

官網上有關 Pagination 說明:http://book.cakephp.org/view/164/pagination

Bakery上的討論:

http://bakery.cakephp.org/articles/view/basic-pagination-overview-3

http://bakery.cakephp.org/articles/view/advanced-pagination-1-2

http://bakery.cakephp.org/articles/view/pagination-recall

CakePHP處理HTTP Request 典型的流程

圖片來源:A Typical CakePHP Request

參考資料: A Typical CakePHP Request

上圖其實也說明了MVC的架構概念以及處理流程!

1. 使用者瀏覽網站(例加:瀏覽 /cake/buy,cake是controller, buy是action,也就是呼叫cake_controller.php 中的 buy函式),這時 your_cakephp1.2/app/webroot/index.php 會收到經由 mod_rewrite 轉換的網址(mod_rewrite會將 /cake/buy 轉成 index.php?url=/cake/buy),在index.php中,使用Dispatcher(your_cakephp1.2/cake/dispatcher.php),把網址傳給Dispatcher。以下是index.php的部分程式碼:

$Dispatcher = new Dispatcher();
$Dispatcher->dispatch($url);

2. Dispatcher中,透過Router (your_cakephp1.2/cake/libs/router.php),取得Controller和Action的名稱。

3. 在開始使用Controller的Action之前,先呼叫這個controller的beforeFilter(也就是圖上 Controller的藍色框所表示的意思)。

4.5.6. 經過 controller 的 beforeFilter 之後,開始呼叫 Action 函式,一般在Action 函式中,會使用者Models來處理資料庫相關的工作,用Components處理像Cookie, Session的相關工作,視你的程式而定,最後將資料透過 set() 的方式,傳給 View 處理。

7. 在View處理版型前,會呼叫 controller 的 beforeRender (也就是 7 箭頭上的藍框)。一般網頁的版型,會有layout、element和自身action的view版型組成,其中會使用helper來協助處理版型。

8. 在處理完版型,回覆給使用者前,Dispatcher會再呼叫 controller 的 afterFilter (也就是 8 箭頭上的藍框。註)

以上就是很典型CakePHP處理Request的流程。

註:

CakePHP官網上說明 Controller 有四個callback函式:beforeFilter, beforeRender, afterRender, afterFilter。不過我在 cake/libs/controller/controller.php 找不到afterRender的定義,也找不到afterRender使用的地方,不知道是我還沒讀透程式碼,還是官方誤植了這個函式。因此上圖的8 箭頭的另一個藍框,應該是指afterRender。

CakePHP 1.2 第一個程式,換掉CakePHP說明首頁。

前提:你已經做好相關設定,如果還沒有的話,請見:CakePHP 1.2 簡易安裝與設定

I. CakePHP 目錄說明:

在寫程式之前,先了解CakePHP是如果安排程式的目錄。基本上,1.1版和1.2版沒有什麼差別。

  • app
  • cake
  • docs
  • index.php
  • vendors

app: 主要是放你網站的程式與靜態的html網頁。

cake: CakePHP的核心程式,當有問題時,也可以到這邊來拆解CakePHP的程式;因為目前CakePHP的說明還不是非常的完整,有時會需要用拆解程式的方式來了解如何使用。

docs: 顧名思義,就是放一些CakePHP的說明文件。

vendors: 如果你有使用其他open source的套件,可以放在這個地方。

app內的目錄:

config: 放設定檔的目錄,可以參考 CakePHP 1.2 簡易安裝與設定
controllers: 放controller程式的目錄,不懂什麼是Controller? 請參考:CakePHP說明 - Controller
locale: 放多國語言的訊息設定檔,這個也是CakePHP 1.2 的新功能。
models: 放model 程式的目錄,不懂什麼是Model? 請參考:CakePHP說明 - Model
plugins: 放別人寫好的CakePHP程式。
tmp: 顧名思義,放一些暫存檔的目錄,有 log, cache 等。
vendors: 同上面的vendors。

views: 放網路程式版型的目錄。請參考:CakePHP說明 - View

webroot: 放靜態網頁的目錄滿,包含圖片, javascript, css等。

參考網頁: http://book.cakephp.org/view/19/cakephp-file-structure

II. 開始你的第一個程式:home_controller.php

首先在 your_cakephp1.2/app/controller 下產生一個檔名是 home_controller.php (為何是 程式_controller.php 方式命名?這是cakephp的規則,請照做!),內容如下:

<?php

class HomeController extends AppController {
public $name = 'Home';
public $uses = null;

// 首頁
public function index() {

}// end index

}

?>

在 your_cakephp1.2/app/views 下,產生一個目錄是 home,在 your_cakephp1.2/app/view/home/ 下,產生一個檔名是 index.ctp (註:1.1的副檔名是.thtml,1.2是 .ctp)。index.ctp內容如下:

<div>

<?php

echo 'hello world';

?>

</div>

程式完成後,請到 app/config下,修改 routes.php 把預設的 Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home')); 改成 Router::connect('/', array('controller' => 'home', 'action' => 'index', 'index')); 下面另外兩個設定,基本上也不需要了,可以把它們註解!

完成上面的步驟,再重新訪問你的網站,就可以看到你首頁的內容了。不過版型還是很奇怪,主要是因為現在的版型外框還是套用cakePHP的版型。請copy一份 your_cakephp1.2/cake/libs/layouts/default.ctp 到 your_cakephp1.2/app/views/layouts下。原本的 default.ctp 內容如下:

<?php

/* 一堆註解... (省略)*/
?>
<!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 __('CakePHP: the rapid development php framework:'); ?>
<?php echo $title_for_layout; ?>
</title>
<?php
echo $html->charset();
echo $html->meta('icon');

echo $html->css('cake.generic');

echo $scripts_for_layout;
?>
</head>
<body>
<div id="container">
<div id="header">
<h1><?php echo $html->link(__('CakePHP: the rapid development php framework', true), 'http://cakephp.org'); ?></h1>
</div>
<div id="content">
<?php
if ($session->check('Message.flash')):
$session->flash();
endif;
?>

<?php echo $content_for_layout; ?>

</div>
<div id="footer">
<?php echo $html->link(
$html->image('cake.power.gif', array('alt'=> __("CakePHP: the rapid development php framework", true), 'border'=>"0")),
'http://www.cakephp.org/',
array('target'=>'_new'), null, false
);
?>
</div>
</div>
<?php echo $cakeDebug; ?>
</body>
</html>

其實index.ctp,可以當成是.php程式,可以有html和php程式碼。

Header內的程式碼:

<?php __('CakePHP: the rapid development php framework:'); ?> 這一行可以刪除,網頁的title總不能顯示不是我們網站的訊息吧。

<?php echo $title_for_layout; ?> 建議保留,如此一來,每個Controller的action可以自行定義網頁的title。當然如果不需要的話,也可刪除,直接填上你的網站title。
echo $html->charset();
建議保留,會去讀取 core.php 的App.encoding設定(預設是UTF-8)。

echo $html->meta('icon'); favicon 設定,可以刪除,改成自己的

echo $html->css('cake.generic'); css 設定,可以刪除,改成自己的。

echo $scripts_for_layout; javascript 程式,可以刪除。


Body內的程式碼:

除了 <?php echo $content_for_layout; ?> 外,其他都可以替換成自己的內容。<?php echo $content_for_layout; ?>主要是CakePHP處理版型時會用到的,也就是顯示剛剛的index.ctp內容的地方。另外,<?php echo $cakeDebug; ?> 也建議保留,在開發模式(core.php中的 Configure::write('debug', 3))時,會顯示所有的變數內容,當改成release模式時(core.php中的 Configure::write('debug', 0)),這裏是不會顯示任何內容的!

如果完成上面的步驟,已經改寫首頁了!

參考內容:

我之前的文章(CakePHP 1.1版本)

CakePHP 說明 - 什麼是MVC架構

CakePHP說明 - Controller

CakePHP說明 - Model

CakePHP說明 - View

CakePHP 1.2 簡易安裝與設定

首先到CakePHP官網 ,下載目前1.2 beta 版並解壓縮。

安裝 Apache + PHP + MySQL,安裝Apache時,建議安裝mod_rewrite。

I. 設定 Apache

在安裝Apache時,建議安裝mod_rewrite,讓你的網站網址更容易SEO接受與分析。

新增一組 Directory 設定,目錄是你的 your_cakephp1.2/app/webroot。設定如下:

<Directory "your_cakephp1.2/app/webroot/">
Options FollowSymLinks
AllowOverride All
Order allow,deny
Allow from all
</Directory>

請設定 AllowOverride All,如此mod_rewrite會參照cakephp目錄中的.htaccess來做轉址。

最後將你的 DocumentRoot 指到your_cakephp1.2/app/webroot。

如果沒有意外的話,你就可以看到cakephp的說明首頁。

最後測試你的mod_rewrite有沒有成功,如果 http://your_domain/pages/displayhttp://your_domain/ 是同一頁,

那就ok了!

II. 設定 Cakephp

還沒開始設定 Cakephp之前,你的Cakephp的說明首頁會有許多警告訊息。

1. DB 設定

在 your_cakephp1.2/app/config/ 有 database.php.default 請copy 或 rename 成 database.php,依照你的Database帳號/密碼設定,加到這個文件檔中。Cakephp預設是使用MySQL,所以設定上應該沒什麼太大的問題。預設有兩組設定,一個是default, 一個是test,如果沒有特別的需求,就把這兩組都設成一樣。

2. Core 設定

在 your_cakephp1.2/app/config 的core.php,有很多cakephp的相關設定,當然你也可以把自己網站上的共用設定寫在這邊,寫法如同cakephp,使用Configure::write;這與cakephp1.1版使用define方式不同,屆時要讀取設定時,請用Configure::read

core.php中,最常用到的設定有:

(1). Configure::write('debug', 2); 這是設定你的網站目前是在開放給外人使用的模式,還是開發模式;簡單來說,當你要開放你的網站時,請把debug設定 0。 通常開發時,是設定成 2;在開發的過程中,你會看到cakephp是如何執行SQL命令。如果你要看更詳細的資訊,包括整個程式的所有變數值,那就設定成 3

(2). Configure::write('Cache.check', true); 這是使用網頁Cache機制的開關,預設是註解的,通常網站都會需要做cache,建議在開發時,先關閉這項功能,等到開發後期調整cache時,再打開使用。

(3). Configure::write('Session.save', 'php'); Session的處理方式,預設是使用php的方式來處理Session。Cakephp也有內建模組,使用Database來處理Session。如果你的網站主機有很多台機器時,那也許可以改用database的方式;另外建議把放Session的table設定在Memory(Heap)的模式,可以加快處理速度。

(4). Configure::write('Security.salt', 'DYhG93b0qyJfIxfs2guVoUubWwvniR2G0FgaC9mi'); 在你的說明首頁上,一開始也會看到這則警告,請把這個值改成你自己的亂數字串即可。這個設定主要是使用在Cookie;Cakephp的Cookie模組有支援cipher加密功能,屆時Cookie會依照這個值來做加密。

(5). Cache::config('default', array('engine' => 'File')); Cache 設定,預設是用檔案的方式來做cache;Cakephp也內建模組,可以使用database, xcache, memcache, apc 等常見的方法來做cache。如果你是使用database也建議你把cache的table設定在Memory(Heap)的模式,可以加快處理速度。

III. 開始寫程式

如果都設定完成,基本上就可以開始寫程式了!

相關網站:

CakePHP官網:http://www.cakephp.org

1.1手冊: http://manual.cakephp.org/

1.2手冊: http://book.cakephp.org

API說明:http://api.cakephp.org/

CakePHP程式碼討論與分享: http://bakery.cakephp.org/