2007年5月29日 星期二

check class

class_exists :
if (class_exists('MyClass')) {
$myclass = new MyClass();
}

interface_exists
// Check the interface exists before trying to use it
if (interface_exists('MyInterface')) {
class MyClass implements MyInterface
{
// Methods
}
}

get_declared_classes
print_r(get_declared_classes());

exec() check

$command = escapeshellcmd($command);
//escapeshellcmd -- Escape shell metacharacters
exec($command)

POST 方法上傳

符合 RFC-1867 標準的瀏覽器
PHP 的這種特性使得我們既可以上傳文本文件,也可以上傳二進制文件。利用 PHP 的認証和文件操作函式,您就可以控制誰有上傳的權限,以及在文件上傳後進行哪些處理。

PHP 也支援 PUT 方法的文件上傳,Netscape Composer 和 W3C 的 Amaya 客戶端使用這種方法。

自動全域變數 $_FILES 從 PHP 4.1.0 版本開始被支援。在這之前,從 4.0.0 版本開始,PHP 支援 $HTTP_POST_FILES 陣列。這些陣列將包含所有關於您上傳的文件的訊息,其中,我們推薦您使用 $_FILES。

我們假設文件上傳字段的名稱如上例所示,為 userfile。


$_FILES['userfile']['name']
客戶端機器文件的原名稱。

$_FILES['userfile']['type']
文件的 MIME 型別,需要瀏覽器提供該訊息的支援,例如“image/gif”。

$_FILES['userfile']['size']
已上傳文件的大小,單位為字節。

$_FILES['userfile']['tmp_name']
文件被上傳後在伺服端儲存的臨時文件名。

$_FILES['userfile']['error']
和該文件上傳相關的錯誤代碼。['error'] 是在 PHP 4.2.0 版本中增加的。
UPLOAD_ERR_OK
值:0; 沒有錯誤發生,文件上傳成功。

UPLOAD_ERR_INI_SIZE
值:1; 上傳的文件超過了 php.ini 中 upload_max_filesize 選項限制的值。

UPLOAD_ERR_FORM_SIZE
值:2; 上傳文件的大小超過了 HTML 表單中 MAX_FILE_SIZE 選項指定的值。

UPLOAD_ERR_PARTIAL
值:3; 文件只有部分被上傳。

UPLOAD_ERR_NO_FILE
值:4; 沒有文件被上傳。


註: 這些在 PHP 4.3.0 之後變成了 PHP 常數。

在 PHP 4.2.0 以上版本,您還可以通過 $_FILES['userfile']['error'] 變數來根據不同的錯誤代碼來做相關的判斷。不管做何種的判斷,您必須將該文件從臨時目錄中刪除,要麼將其移動到其它的地方。

如果該文件沒有被移動到其它地方也沒有被改名,則該文件將在表單請求結束時被刪除。

2007年5月25日 星期五

foreach

$array = array("1"=>"a","2"=>"b","3"=>"c","4"=>"d","5"=>"e");
foreach($array as $key => $val){
$i = 1;
echo $i."@@".$val."
";
$i++;
}

Result:
1@@a
1@@b
1@@c
1@@d
1@@e

Group , Join

Group :
1. mysql_num_rows(user_group_34) = mysql_num_rows(efun_group) = 4
2. where only one rule , if wrong may make (Cartesian join)笛卡兒連接
=> 4*4 = 16 筆
SELECT G.s_name,U.memeber_id FROM user_group_34 U, efun_group G
WHERE U.group_id = G.id
GROUP By G.s_name

s_name member_id
group1 9
group2 9
group3 9
group4 9

Join
CROSS JOIN
 
兩個表格在結合時,不指定任何條件,如:
SELECT employee.realname, salary.amount FROM employee, salary
SELECT employee.realname, salary.amount FROM employee JOIN salary
SELECT employee.realname, salary.amount FROM employee CROSS JOIN salary
 在這個例子中,employee 原有 4 筆資料,而 salary 有 5 筆資料,在 JOIN 之後,結果將是兩者資料筆數的乘積:20。就等於是將兩個資料表中,所有可能的組合全部列出來一樣,其結果在實務上不見得有意義。這種結合可被視為兩個資料表的「笛卡兒乘積(Cartesian product)」。《執行結果》

INNER JOIN
 兩個表格在結合時,指定彼此之間的結合條件,如:
SELECT employee.realname, salary.amount FROM employee, salary
WHERE employee.employee_id = salary.employee_id
SELECT employee.realname, salary.amount FROM employee
JOIN salary ON employee.employee_id = salary.employee_id
SELECT employee.realname, salary.amount FROM employee
INNER JOIN salary ON employee.employee_id = salary.employee_id
 如此一來,只有符合結合條件(同時存在於彼此之間)的資料,才會被 JOIN 在一起。這是最常用的 JOIN 型式。《執行結果》

OUTER JOIN
 兩個表格在進行 INNER JOIN 時,只有彼此相符合的資料列才會被考慮到,除此之外,就完全被忽略了。相較於 INNER JOIN 的排他性,OUTER JOIN 則是「寬容」多了。
 在進行 LEFT OUTER JOIN 時,除了彼此相符合的資料列以外,左方的資料表中不相符的資料列也會被強迫輸出,如:
SELECT employee.realname, salary.amount FROM employee
LEFT OUTER JOIN salary ON employee.employee_id = salary.employee_id
SELECT employee.realname, salary.amount FROM employee
LEFT JOIN salary ON employee.employee_id = salary.employee_id
 像 Chuang 這種僅出現在 empolyee 裡,不存在於 saraly 中的資料列,在搭配 NULL 值之後,也能被列在結果之中了。善用這種特殊結果,我們可以順利找到只存在前一資料表,而不存在於後一資料表的資料列。《執行結果》

NATURAL JOIN
 NATURAL 又代表什麼?加上這個關鍵字之後,兩個表格在進行 JOIN 時,不必言明彼此的結合關係,兩者之間同名的欄位會被自動結合在一起。
 所以,以下兩段語法的執行結果相同:
SELECT employee.realname, salary.amount FROM employee
INNER JOIN salary ON employee.employee_id = salary.employee_id
SELECT employee.realname, salary.amount FROM employee
NATURAL JOIN salary
 以下兩段語法的執行結果也是相同的:
SELECT employee.realname, salary.amount FROM employee
LEFT JOIN salary ON employee.employee_id = salary.employee_id
SELECT employee.realname, salary.amount FROM employee
NATURAL LEFT JOIN salary

fetch query result

$sql = "SELECT * from user WHERE s_user_account = '".$account."'";
$query = $this->db->query($sql);

return $query ://只送回query的第一筆資料,需要搭配query->row_array()才能 praser出array
CI_DB_mysql_result Object ( [conn_id] => Resource id #25 [result_id] => Resource id #28 [result_array] => Array ( ) [result_object] => Array ( ) [current_row] => 0 [num_rows] => 0 )

return $query -> result: ://送回query的全部資料
Array (
[0] => stdClass Object ( [id] => 1 [member_id] => 9 [group_id] => 1 [s_role] => u [approver_id] => 8 )
//////////////////////////////////
[1] => stdClass Object ( [id] => 3 [member_id] => 9 [group_id] => 2 [s_role] => u [approver_id] => 8 )
[2] => stdClass Object ( [id] => 5 [member_id] => 9 [group_id] => 3 [s_role] => u [approver_id] => 8 )
[3] => stdClass Object ( [id] => 7 [member_id] => 9 [group_id] => 4 [s_role] => u [approver_id] => 8 )
)

return $query
$user = $query->row_array();
Array ( [id] => 9 [s_user_account] => windharry [s_password] => windharry [n_shard] => 1 [n_hash] => 34 [s_email] => windharry@mail.com [s_blog_title] => [d_create_time] => 2007-05-23 16:25:28 [d_update_time] => 2007-05-23 16:25:28 )

2007年5月23日 星期三

kkwi

http://news.chinatimes.com/Chinatimes/ExteriorContent/ChinatimesWeekly/newweekly-content/0,3813,170205+96051111,00.html

2007年5月22日 星期二

20070522 Mysql Driver 編碼問題

solution1:
強制指定編碼.

/systems/database/drivers/mysql/mysql_diver.php

function _execute($sql)
{
$sql = $this->_prep_query($sql);
@mysql_query('SET NAMES utf8', $this->conn_id);// add by Harry Yao 20070522
return @mysql_query($sql, $this->conn_id);
}

2007年5月21日 星期一

ignore_user_abort()

這函式似乎很少看到...
以前也沒用過
但今天用上了
事情是這樣發生的...

弄了一個空間
讓人用FTP上傳檔案
Web部分,作檔案瀏覽的介面
對於圖檔/視訊檔,作縮圖,並且視訊檔會轉成flv提供線上播放
作縮圖和轉flv都是
轉檔的動作都寫在thumb.php裡

用exec()執行外部程式再用ffmpeg從flv弄出jpg

但發現有的大一點的視訊檔
圖檔會生不出來
去翻存那些轉出來檔案的資料夾
發現只有flv

原因是
轉flv時轉檔轉太久
timeout後(或完成前使用者離開這一頁)browser放棄了,並告訴server不要檔案了
然後這個php沒執行完就被中斷了
所以弄出jpg檔的動作沒做到

後來用以下兩行解決
ignore_user_abort(true);
set_time_limit(0);

ignore_user_abort()可以讓php不會被中斷
於是一系列動作都會乖乖的執行完

=>
1.透過這函式應能寫出類似 crontab 的功能
2.發較大量信件的時候萬一使用或者瀏覽器中斷,發送動作還是會繼續做完.
mencoder
ffmpeg
imagemagick
之類的

其中視訊檔的縮圖,是先用
mencoder轉flv

換掉別人的網站首頁

可以用
圖層的概念.. 用一個長寬100%的div蓋掉原本的畫面



2007年5月20日 星期日

php

http://www.phppatterns.com/docs/design/archive/model_view_controller_pattern#the_controller

2007年5月15日 星期二

CakePHP使用手冊-命名規則?

轉貼自 http://www.ezluk.org/

是的,命名規則(convention)。從thefreedictionary:
可以查到Convention有幾個意思:




  1. General agreement on or acceptance of certain practices or
    attitudes: By convention, north is at the top of most maps.





  2. A practice or procedure widely observed in a group, especially
    to facilitate social interaction; a custom: the convention of
    shaking hands.





  3. A widely used and accepted device or technique, as in drama,
    literature, or painting: the theatrical convention of the
    aside.





Cake中的命名規則是讓魔法發生的關鍵,我們把它叫automagic
不用說以命名規則進行一些設定有多好用,Cake甚至讓你的生產力提昇到驚人的等級,卻又不彈性。
Cake裡的命名規則既簡單又直觀。它是由web開發者多年來的實用經驗設計出來的。




第二節



檔名



檔名是由底線將文字分開。
一般規則中,名為MyNiftyClass的類別,存放的檔名就得叫my_nifty_class.php



如果有看到一些Cake的程式片斷,自然就會知道:




  1. 如果有個Controller名叫KissesAndHugsController
    那它的檔名叫一定叫kisses_and_hugs_controller.php
    (注意檔名內的_controller)





  2. 如果它的Model名稱叫OptionValue
    那它的檔名一定是option_value.php





  3. 若是個名叫MyHandyComponent的Component,
    那麼檔名就是my_handy.php(和controller不同,不需要加_component)。





  4. 若是個名為BestHelperEver的Helper,
    檔名一定是best_helper_ever.php






第三節



Model





  1. Model的類別名稱是單數.





  2. Model的類別名稱,若只有一個單字則第一個字大寫,若由多個單字組成則每個單字第一個字母大寫。


    例如: Person, Monkey, GlassDoor, LineItem, ReallyNiftyThing





  3. 多對多Join資料表需命名為:
    第一個資料表複數_第二個資料表複數


    例如: tags_users





  4. Model的檔名用小寫加底線。


    例如: person.php, monkey.php, glass_door.php,
    line_item.php, really_nifty_thing.php






  5. Model對應的資料庫資料表同樣使用小寫加底線,但是用複數
    Database tables related to models also use a lower-case
    underscored syntax - but they are plural.


    例如: people, monkeys, glass_doors, line_items,
    really_nifty_things


    譯註:person複數型原來是people!看來還是得懂些英文,難怪我用persons不行!






CakePHP的命名規則主要是要讓程式撰寫更流暢,提昇程式碼的可讀性。
如果你覺得它實在礙手礙腳,那就用自己的方法吧,Cake同樣也可以接受。
但得多做二件事:





  1. 定Model名稱: 在model定義中設定$name變數。





  2. 定Model對應的資料表:在model定義中設定$useTable變數







第四節



Controller





  1. Controller類別名稱是複數





  2. Controller類別名稱如果只有一個單字則第一個字母大寫,若是多個單字則每個單字的第一個字母大寫。
    Controller類別名稱還必需在最後加上'Controller'。



    例如: PeopleController, MonkeysController,
    GlassDoorsController, LineItemsController,
    ReallyNiftyThingsController





  3. Controller檔名用小寫加底線,同樣必需在最後加上'_controller'字串。
    所以,如果有個controller叫PostsController,檔名就應該叫posts_controller.php



    例如: people_controller.php, monkeys_controller.php,
    glass_doors_controller.php, line_items_controller.php,
    really_nifty_things_controller.php





  4. protected成員函式,在函式名前加'-'。





  5. private成員函式,在函式名前加'--'。






第五節



View





  1. View由顯示他們的action名稱命名





  2. 將檔名命名為action名稱的小寫。



    例如: PeopleController::worldPeace() 需要一個view,檔名為
    /app/views/people/world_peace.thtml;
    MonkeysController::banana() 需要一個view,檔名
    /app/views/monkeys/banana.thtml.





也可以強制action使用某一個view,只要在action結束前呼叫$this->render('view檔名去除副檔名後的字串');。







第六節



Helper





  1. Helper類別名稱是以第一個字母大寫的單字組成,最後面再加上"Helper"字串。檔名則使用小寫加底線去除"helper"。



    例如: MyClarinetHelper放在/app/views/helpers/my_clarinet.php內。





在controller中引用的方式為:var $helpers = array('Html','MyHelper');。
接著就可以在view裡這麼呼叫:$myHelper->method().





第七節



Component





  1. Component類別名稱是以第一個字母大寫的單字組成,最後面再加上"Component"字串。檔名則使用小寫加底線去除"component"。



    範例: MyComponentComponent放在
    /app/controllers/components/my_component.php









在controller內引用方式為:var $components array('MyComponent');。
接著在controller內呼叫$this->MyComponent->method()。





第八節



Vendor



Vendor沒有任何命名規則,原因很簡單:他們是第三方的程式碼,Cake對他們沒有控制權。


CakePHP使用手冊-暫存機制(Cache)

轉貼自 http://www.ezluk.org/

第一節



這是什麼?


從0.10.9.2378_final版之後,Cake開始支援view暫存(也叫全頁暫存)。
不,我們並沒有開玩笑。
你現在可以將layout和view暫時存放。
還可以將view的某部分標記,讓暫存機制忽略它。
這個功能如果巧妙應用,程式效能就能有效提昇。


當你送出一個URL時,Cake會先檢查這個URL在暫存資料內是否存在。
如果有,Cake就會直接將暫存版的資料回傳。
如果找不到,則動作就和一般沒二樣。


如果你已啟動Cake的暫存功能,Cake會把一般操作的輸出結果放在暫存空間內,讓未來的使用者使用。
下次網頁再被呼叫時,Cake就直接從暫存空間內將資料取出傳回。很棒吧!
讓我們仔細看看如何使用這個功能。



第二節



如何使用?



啟動暫存功能


預設,view暫存的功能是被關閉的。
要啟動它,首先需要更改/app/config/core.php檔內的CACHE_CHECK,由false改成true:



/app/config/core.php (部分)



define ('CACHE_CHECK', true);


這一行告訴Cake你要啟動View暫存功能。



在想要暫存的view的controller裡,必須將Cache helper加到$helpers陣列中





var $helpers = array('Cache');



接下來,就得指定要暫存的東西。




Controller變數$cacheAction


這一節,我們將教你如何告訴Cake要暫存什麼。
透過設定controller變數$cacheAction就可以做到。
$cacheAction要被設成陣列,內含想要暫存的action名稱,和想要保留的時間。
時間的指定必需是strtotime()能接受的字串(如'1 day' 或'60 seconds')。


假設我們有一個ProductsController,其中有一些東西想暫存。
以下的範例示範如何使用$cacheAction告訴Cake要暫時存放的東西為何。




$cacheAction 範例




//將最近常被流覽的產品網頁暫時存放六小時:

var $cacheAction = array(

    'view/23/'  => 21600,

    'view/48/'  => 21600

);

//暫存整個action。此例中會將rqcalled產品列表暫時存放一天:

var $cacheAction = array('recalled/' => 86400);

//如果想要,也可以將每一個action暫存起來,只要傳入一個時間字串:

//這個時間字串是strtotime()能接受的格式,表示存放的時間。

var $cacheAction = "1 hour";

//你也可以在某個action內定義暫存的內容,只要呼叫$this->cacheAction = array()...

   






標記View的內容


有時候,我們可能不想讓view內所有的內容都被暫存起來。
如果有些地方是用于展示新產品,你就會要Cake在暫存此頁時,不要將那一部分暫存。



要指定不被暫存的內容,只要將這些內容用<cake:nocache> </cake:nocache>標籤包起來即可。




<cake:nocache> 範例


<h1> New Products! </h1>

<cake:nocache>

<ul>

<?php foreach($newProducts as $product): ?>

<li>$product['name']</li>

<?endforeach;?>

</ul>

</cake:nocache>

 





清除暫存資料


首先要知道,如果資料庫有變更,Cake就會自動清除暫存資料。
例如,如果有個view用到Post model內的資訊,而Post曾被INSERT,UPDATE或DELETE過,Cake就會清除這個view的暫存資料。


但,有些狀況你會想自己清除某些暫存資料。
Cake也提供了clearCache()函式來做這件事,而它是全域函式:

clearCache() 範例


//清除名稱為'controller'的所有暫存網頁
clearCache('controller');

//清除名稱為'controller_action'的所有暫存網頁
clearCache('controller_action/');

//清除名稱為'controller_action_params'的所有暫存網頁
//註:可以有多個params
clearCache('controller_action_params');

//也可以用陣列一次清除多個網頁
clearCache(array('controller_action_params','controller2_action_params));





第三節



幾個要點


下面列出關於暫存功能的幾個要點:




  1. 設定 /app/config/core.php檔內的CACHE_CHECK啟動暫存功能。




  2. 在想要暫存的view的controller內,將Cache helper加到$helpers陣列中。




  3. 使用$cacheAction指定暫存的action。




  4. view裡不想被暫存的內容,用<cake:nocache> </cake:nocache>標籤包起來。




  5. 如果資料庫內容改變,Cake會自動清除有用到此內容的暫存資料。




  6. 使用clearCache()手動清除一些暫存資料。




CakePHP使用手冊-安全性元件(Security Component)

轉貼自 http://www.ezluk.org/

安全性元件(Security Component)


第一節



引言


Security component是用來避免controller action受到惡意或錯誤的request攻擊。
它讓你可以設定action可以被呼叫的條件,並可指定不合條件事如何處置。
同樣的,在使用Security component前,得先確定'Security'有出現在controller的$components陣列裡。



第二節



保護Controller的Action


Security component包含二個主要方法限制對controller action的使用權:





  • requirePost

  • string $action1

  • string $action2

  • string $action3...



特定的action必需透過POST呼叫才能執行。





  • requireAuth

  • string $action1

  • string $action2

  • string $action3...



比較POST過來的表單資料內的認証金鑰和存在使用者的session內的認証金鑰是否相同,如果相同就允許執行這個action。
這裡得注意一點,為了保有彈性,只有透過POST傳資料才會啟動作。
如果是由一般的GET request呼叫action,requireAuth()則不會有任何動作。
為了達到最高的安全性,你應該在想要完整保護的action內使用requirePost()強制使用POST,再用requireAuth()檢查金鑰。
第四節會再仔細說明認証金鑰是如何產生,如何消失。但先讓我們看個簡單的範例:



class ThingsController extends AppController

{

    var $components = array('Security');



    function beforeFilter()

    {

        $this->Security->requirePost('delete');

    }



    function delete($id)

    {

        //這個動作只有透過HTTP POST request才能執行

        $this->Thing->del($id);

    }

}

 


這兒,我們告訴Security component 'delete' action必需透過POST request才能執行。
通常我們會將告訴Security(和其他大部分的component)要怎麼做的程式放在beforeFilter()裡。
因為beforeFilter()會在action執行前被呼叫,接著立即執行action,這個時間點正是我們需要的。


你可以試著在流覽器內輸入這個action的URL,看看會發生什麼事。



第三節



處理非法的Request


所以,如果有個request不符合我們設定的安全需求,又會發生什麼事呢?
預設,這個request會變黑洞,client會收到404檔頭,應用程式立即中止。
然後,Security component還有個$blackHoleCallback屬性,讓你設定成定義在controller裡的回呼函式名稱。



除了單純給個404檔頭然後不做任何回應外,這個屬性可以讓你對此request做一些額外的檢查,
將它導向另一個位置,或甚至將對方的IP位置記錄下來。
然而,如果你選擇了使用回呼函式,那麼在request不合法時結束程式就完全是你的責任了。
如果回呼函式傳回true,否則Security component會繼續另一個檢查另一個安全需求。
否則,程式會停止檢查動作,繼續執行下面的行為,不會中止。



第四節



進階Request認証


requireAuth()函式允許你仔細的設定action可以從那兒執行與如何執行,但它同樣也有一些規定在,
在你了解認証動作的執行方法後就會明白。
如上述,requireAuth()是將POST資料與使用者的session資料內的認証金鑰相比較。
所以,所以在收到request和發出request的二個controller內都必需包含Sequrity component。



例如,如果有一個PostController的action,它的view內含表單會發出POST rquest呼叫CommentsController的action,
那麼,CommentsController和PostsController 都要包含Security component。



每次載入Security compoent時,即使它並沒有被用來保護任何action,都會做這些事:
首先,用核心的Security類別產生一個認証金鑰。接著,將這個金鑰寫到session裡,同時附上過期時間和額外的資訊(
過期時間可以在/app/config/core.php內的session安全設定中設定)。
然後,在隨之使用的controller內設定此金鑰。



接著,在view檔內任何使用$html->formTag()產生的表單標籤都會暗藏內含認証金鑰的輸入欄位。
在表單被POST時,Security component就可將此值與session裡的值(放在rquest最後面)比對。
隨後,認証金鑰會被重建,所有動作再重覆一次。


CakePHP使用手冊-要求處理元件

轉貼自 http://www.ezluk.org/

第一節



引言


RequestHandler component在Cake中被用來判定傳回的HTTP reqeust。
你可以用它通知controller有Ajax request,取得遠端client的IP位置和request種類,或去除不要的資料。
要使用RequestHandler component,得確認controller的$components陣列是否包含了這個component。



class ThingsController extends AppController

{

    var $components = array('RequestHandler');



    // ...

}


第二節



取得client/Request訊息


就讓我們開門見山,直接看函式說明:





  • accepts

  • string $type



依$type值傳回client接受的content-type。
如果$type等於null或沒有傳值,會傳回內含client能接受的所有content-type的陣列。
如果傳了一個字串過去,則會將$type拿去和content-type表(參考setContent())比對,若client可以接受這個種類時傳回true。
如果$type是一個陣列,每個字串會分別比對,如果其中一個能接受就傳回true。例如:



class PostsController extends AppController

{

    var $components = array('RequestHandler');



    function beforeFilter ()

    {

        if ($this->RequestHandler->accepts('html'))

        {

            // 當client接受HTML(text/html)時才執行這裡的程式

        }

        elseif ($this->RequestHandler->accepts('rss'))

        {

            // 當client接受RSS(application/rss+xml)時才執行這裡的程式

        }

        elseif ($this->RequestHandler->accepts('atom'))

        {

            // 當client接受atom(application/atom+xml)時才執行這裡的程式

        }

        elseif ($this->RequestHandler->accepts('xml'))

        {

            // 當client接受XML(application/xml 或 text/xml)時才執行這裡的程式

        }



        if ($this->RequestHandler->accepts(array('xml', 'rss', 'atom')))

        {

            // 當client接受XML,RSS,ATOM其中之一時才執行這裡的程式

        }

    }

}





  • getAjaxVersion




若使用Prototype JS 函式庫,它會在Ajax request上放置一段特殊表頭資料。
此函式可以傳回檔頭內記錄的Protytype版本資訊。





  • getClientIP




傳回client的IP位置。





  • getReferrer




傳回最出發出這個request的server名稱。





  • isAjax




如果目前的request是XMLHttpRequest就傳回true。





  • isAtom




如果client能接受Atom格式的內容則傳回true。





  • isDelete




若目前的request的'REQUEST_METHOD'等於DELETE則傳回true。





  • isGet




若目前的request的'REQUEST_METHOD'等於Get則傳回true





  • isMobile




如果HTTP_USER_AGENT說明了這是個手機的web流覽器則傳回true。





  • isPost




若目前的request的'REQUEST_METHOD'等於POST則傳回true





  • isPut




若目前的request的'REQUEST_METHOD'等於PUT則傳回true





  • isRss




若client能接受RSS格式的內容(application/rss+xml),則傳回true。





  • isXml




若client能接受XML格式的內容(application/xml 或 text/xml),則傳回true。





  • setContent

  • string $name

  • string $type



在content-type的別名表中加入一個選項,與accepts()和prefers()配合使用。
$name是別名名稱,$type則是MIME型別。
內建的幾種格式為:



// Name     => Type
'js' => 'text/javascript',
'css' => 'text/css',
'html' => 'text/html',
'form' => 'application/x-www-form-urlencoded',
'file' => 'multipart/form-data',
'xhtml' => array('application/xhtml+xml', 'application/xhtml', 'text/xhtml'),
'xml' => array('application/xml', 'text/xml'),
'rss' => 'application/rss+xml',
'atom' => 'application/atom+xml'



第三節



精簡資料


有時候我們會想刪除request或輸入的資料內部分內容。
下列的RequestHandler函式可以做這類的事。





  • stripAll

  • string $str



刪除$str內所有的空白,影像和script(就等於同時呼叫stripWhitespace(),stripImages()和stripScripts())。





  • stripImages

  • string $str



刪除$str裡的影像。





  • stripScripts

  • string $str



移除$str裡所有<script> 和<style> 相關的標籤。





  • stripTags

  • string $str

  • string $tag1

  • string $tag2...



移除$str裡$tag1,$tag2等參數指定的標籤。


$someString = '<font color="#FF0000"><bold>Foo</bold></font> <em>Bar</em>';



echo $this->RequestHandler->stripTags($someString, 'font', 'bold');



// 輸出: Foo <em>Bar</em>




  • stripWhiteSpace

  • string $str



移除$str內的空白字元。



第四節



其他好用的函式


當應用程式使用到AJAX技術時,RequestHandler component更會顯得特別好用。
setAjax()函式可以自動偵測AJAX的request,然後將controller的layout轉換成AJAX layout。
這樣的好處在於你可以做一個小視窗,在收到AJAX request時變大二倍。


// list.thtml

<ul>

<? foreach ($things as $thing):?>

<li><?php echo $thing;?></li>

<?endforeach;?>

</ul>



//-------------------------------------------------------------



//The list action of my ThingsController:

function list()

{

    $this->RequestHandler->setAjax($this);

    $this->set('things', $this->Thing->findAll());

}

 

當一般的流覽器呼叫/things/list時,沒排序的列表會被畫在應用程式預設的layout上。
但如果這是一個AJAX的rquest,列表就會自動被畫在AJAX layout上。


CakePHP使用手冊-資料過濾

轉貼自 http://www.ezluk.org/

資料過濾


第一節



程式中使用Sanitize


Cake內建的Sanitize類別是用來防止使用者傳送惡意攻擊資料或其他不想要的資料
Sanitize是核心函式庫的一部分,所以可以在程式中任何一個地方使用,但最好是在controller或model裡使用。



// 首先,把核心函式庫包含進來:

uses('sanitize');

// 接下來,建立Sanitize物件:

$mrClean = new Sanitize();

// 從這裡開始就可以使用Sanitize清除資料

// (下節會介紹Sanitize類別中可以使用的方法)



第二節



讓資料安全地在SQL和HTML裡使用


這一節會說明如何使用Sanitize類別所提供的一些函式。





  • paranoid

  • string $string

  • array $allowedChars



此函式會將$string裡非文字的資料去除。
然而,你也可以把想要保留的字元放在$allowedChars陣列裡。



$badString = ";:<script><html><   // >@@#";

echo $mrClean->paranoid($badString);

// 輸出: scripthtml

echo $mrClean->paranoid($badString, array(' ', '@'));

// 輸出: scripthtml    @@




  • html

  • string $string

  • boolean $remove = false



這函式幫你將使用者提交的HTML資料以純文字的模式直接顯示在既存的HTML layout上。
當不想讓使用者破壞你的layout或在blog的文章內插入影像或script時特別有用。
如果$remove設成true,所有的HTML標籤都會被刪除,而不是直接把HTML檔字串看列印。



$badString = '<font color="#FF0000">HEY</font>';

echo $badString;

//輸出:HEY

echo $mrClean->html($badString);

// 輸出: <font color="#FF0000">HEY</font>

echo $mrClean->html($badString, true);

// 輸出: font color=#FF0000 HEY font





  • sql

  • string $string



將SQL指令脫逸(加上斜線),讓SQL指令被指為一般文字處理。
處理方法依系統magic_quotes_gpc 變數的設定值決定。





  • cleanArray

  • array @$dirtyArray



這個函式的功能十分強大,是個多功能的清理器,可以用於整個陣列上(如$this->params['form'])。
這函式傳入一個陣列,然後將它清理一翻:沒有傳回值,因為直接傳入參照。
下面的清理動作會作用在陣列內每個元素上(遞迴):




  1. 奇怪的空格(包含0xCA)會被用一般的空格取代




  2. HTML字串會被用正確的HTML標籤取代(如\n 換成 <br>).




  3. 再次檢查特殊字元,移除換行字元,增進SQL的安全性。




  4. 為SQL指令加上斜線(和上頭的sql函式一樣)。




  5. 把使用者輸入的反斜線換成可信任的反斜線。




CakePHP使用手冊-Session元件(Session Component)

轉貼自 http://www.ezluk.org/

Session元件(Session Component)


第一節



Cake內Session的儲存參數


Cake內建三種方式存放session資料:放在暫存檔,使用PHP預設機制,或存放在資料庫,預設使用PHP預設機制。
如果想改成使用暫存檔或資料庫,請編輯核心設定檔:/app/config/core.php
依需要可以把CAKE_SESSION_SAVE變數改成'cake','php'或'database'三者之一。



core.php Session 設定


/**

 * CakePHP includes 3 types of session saves

 * database or file. Set this to your preferred method.

 * If you want to use your own save handler place it in

 * app/config/name.php DO NOT USE file or database as the name.

 * and use just the name portion below.

 *

 * Setting this to 'cake' will save files to /cakedistro/tmp directory

 * Setting it to 'php' will use the php default save path

 * Setting it to 'database' will use the database

 *

 *

 */

define('CAKE_SESSION_SAVE', 'php');


為了要將session資料存在資料庫,必須在資料庫內建立資料表。
資料表的schema放在/app/config/sql/sessions.sql內。



第二節



使用Cake的Session Component


Cake的session component用來與session資料互動。
它包含了對session資料最基本的讀寫動作,還包含錯誤訊息和接受訊息(如"Your data has been saved")等。
在所有的controller裡預設是可以使用Session component的。





  • check

  • string $name



檢查$name是否已經存於session裡。





  • del

  • string $name




  • delete

  • string $name



刪除$name這個session變數。





  • error




傳回Session component內所發生最後一個錯,常用於除錯。





  • flash

  • string $key = 'flash'



傳回session內用setFlash()所設定的最後一個訊息。
如果有指定$key,則會選用以該鍵存放的訊息中最近的一條。





  • read

  • string $name



傳回名為$name的session變數。





  • renew




建立新的session ID,重新目前使用中的session,刪除舊的,並將刪session的資料傳給新的。





  • setFlash

  • string $flashMessage

  • string $layout =
    'default'


  • array $params

  • string $key = 'flash'



將$flashMessage寫到session內(稍後可由flash()取得)。


如果$layout設成'default',訊息會以'<div class="message">'.$flashMessage.'</div>'型式儲存。
如果$layout設成'',訊息會原封不動的被存放。
如果設成其他值,則使用$layout指定的方式存放。


$params是留著未來使用的,目前沒有作用。


$key則可以讓這個訊息以$key鍵存放,呼叫flash()時可依不同鍵取回訊息。





  • valid




如果session有效則傳回true。
最好在read()前使用,以確認讀得到資料。





  • write

  • string $name

  • mixed $value



將名稱為$name,值為$value的session變數存放於目前的session中。


CakePHP使用手冊-權限控制表(ACL)

轉貼自 http://www.ezluk.org/

權限控制表(ACL)


第一節



了解ACL運作方式


大部分強大又重要的東西都需要一些權限控制。
權限控制表是一種分級明確又好管理的權限控制方式。
權限控制表(或簡稱ACL)主要管理二種事物:需要使用服務的事物,和被控制的事物。
以ACL的角度看,需要使用服務的事物(通常是使用者)叫access request object,簡稱ARO。
而系統內被控制的事物(通常是action或資料)叫access control object,簡單ACO。
每一個對象被稱為一個物件(object),因為有時候這些對象並不是人-有時候可能是程式中另一部分的邏輯。
ACO可以是任何你想要控制的東西,從controller的action 到一項web service,甚至是你祖母的線上日記裡的一行文字。


用一句話來說明這三個簡稱:ACL是用來決定ARO是否可以使用ACO的規範。



為了讓你更加了解這個概念,讓我們舉個實用的例子。
一群魔戒中的勇者們共同使用一組電腦系統。隊長必須在努力衝次任務的同時,在成員間守住一定程度的秘密與安全性。
ARO包含下面幾位:



Gandalf
Aragorn
Bilbo
Frodo
Gollum
Legolas
Gimli
Pippin
Merry

這些是系統中會要求使用服務的使用者(ARO),他們要使用的東西就是ACO。
這裡可以注意到,ACL並不是一種使用者認証系統。
你應該早有另一套存放使用者資料,並在他們進入系統時確認身份的方法。
在確認道使用者身份之後,才是ACL 站出發揮功用的時機。好,話題回到我們的勇者們身上。



Gandalf下一步得做的事是列出系統要管理的物品列表(ACO)。看起來會像這樣:



Weapons
The One Ring
Salted Pork
Diplomacy
Ale

傳統的方法裡,系統會用矩陣的方式管理,矩陣中顯示使用者與各物品間的使用權限。
若將這些資料成列成表,看起來就像下面所示,'X'表示拒絕存取,'O'表示允許存取:




Weapons The One Ring Salted Pork Diplomacy Ale
Gandalf X X O O O
Aragorn O X O O O
Bilbo X X X X O
Frodo X O X X O
Gollum X X O X X
Legolas O X O O O
Gimli O X O X X
Pippin X X X O O
Merry X X X X O

這樣的設計,看起來很完善。既可以保守機密(只有Frodo可以拿到魔戒),又可以防止意外發生(哈比人碰不到肉乾)。
權限似忽設計的很好,也很容易看得懂,對吧?



對這麼一個小系統而言,矩陣的的設定方式也許已經足夠。
但面對會慢慢變大的系統或系統裡有一大堆資源(ACO)和使用者(ARO)時,就無法這麼輕易的建立這個表了,比如說要為每個單位分配使用上百個營地。
矩陣的另一個缺點是無法真的為使用者分組,或依不同的組別給與不同的權限。
例如,我們想在戰爭結束後解除哈比人對酒和肉乾的禁令:
若只能分別更改每個使用者的權限,不但要改的項目很多,出錯的機率也非常高;若有辦法直接更改'哈比人'這一組的權限,一切就簡單多了。



ACL 以樹狀結構進行設計,通常會有一棵ARO的樹和一棵ACO的樹。
把物件整理成樹狀圖,不但可以做細部的設定,還可以以巨觀的方式管理。
身為一個叡智的領導者,Gandalf選擇在新系統中使用ACL,把他的物件整理如下:




Fellowship of the Ring
Warriors
Aragorn
Legolas
Gimli
Wizards
Gandalf
Hobbits
Frodo
Bilbo
Merry
Pippin
Vistors
Gollum

將我們的團隊以這種方式整理之後,便可以對這棵樹的每個結點定義使用權限了。
預設的權限是所有東西都不能使用,接者向下層一項一項權限開放。
最後開放的一定是最在意的事物。所以,依據ARO樹,Gandalf把權限如此設計:



Fellowship of the Ring: [Deny: ALL]
Warriors [Allow: Weapons, Ale, Elven Rations, Salted Pork]
Aragorn
Legolas
Gimli
Wizards [Allow: Salted Pork, Diplomacy, Ale]
Gandalf
Hobbits [Allow: Ale]
Frodo
Bilbo
Merry
Pippin
Vistors [Allow: Salted Pork]
Gollum

若想透過ACL 看看Pippin是否可以拿到Ale,首先查出他在樹中的路徑是Fellowship->Hobbits->Pippin。
然後看看每個節結的權限,其中對Pippin最明確的設定就是我們想得知的答案。




  1. Fellowship = DENY Ale,所以不允許(因為被設成所有東西都不允許)




  2. Hobbits = ALLOW Ale,所以允許




  3. Pippin = ?; 這裡沒有做任何特別的設定。




  4. 最終結論:允許使用ale。




我們還可以透過這棵樹對更底層做更細節的設定,變更上層的設定:



Fellowship of the Ring: [Deny: ALL]
Warriors [Allow: Weapons, Ale, Elven Rations, Salted Pork]
Aragorn [Allow: Diplomacy]
Legolas
Gimli
Wizards [Allow: Salted Pork, Diplomacy, Ale]
Gandalf
Hobbits [Allow: Ale]
Frodo [Allow: Ring]
Bilbo
Merry [Deny: Ale]
Pippin [Allow: Diplomacy]
Vistors [Allow: Salted Pork]
Gollum

你可以發現,Aragorn的權限雖然和所屬的Warrior組一樣,但仍可以單獨給他特別的權限。
再說明一次,我們把預設權限設成DENY,然後一層層向下,將想開放的設回ALLOW。
想看看Merry是否可以拿到Ale,先查一下Merry在這棵樹的路徑為:Fellowship->Hobbits->Merry,
然後查出每個節點所設與ale相關的權限:




  1. Fellowship = DENY 因為設定為全部拒絕




  2. Hobbits = ALLOW: ale, 所以允許




  3. Merry = DENY ale, 所以拒絕




  4. 最終結論:不能使用ale。





第二節


定義權限:Cake的INI型ACL


Cake的第一套ACL系統是透過存於Cake安裝設定裡的INI檔進行設定。
雖然它既實用又穩定,我們還是建議您使用以資料庫為基礎的ACL,最大原因是它可以動態建立ACO和ARO。
舊的ACL(ini版)在簡單的應用中還是非常好用,特別是對那些不想使用資料庫的人而言。



ARO/ACO的權限被定義在
permissions are specified in/app/config/acl.ini.php中。
使用的設定指定可以在acl.ini.php檔的開頭找到說明:


; acl.ini.php - Cake ACL 設定

; ----------------------------------------

; 使用這個檔案指定使用者權限

; aco = access control object (系統裡的某樣事物)

; aro = access request object (需要使用服務的某樣事物)

;

; 使用者資料加入方法如下:

;

; [使用者名稱]

; groups = group1, group2, group3

; allow = aco1, aco2, aco3

; deny = aco4, aco5, aco6

;

; 群組資料加入方法也差不多:

;

; [群組名稱]

; allow = aco1, aco2, aco3

; deny = aco4, aco5, aco6

;

; allow, deny, 和 groups 都可以省略。

; 注意:群組名稱千萬*不可以*和使用者名稱相同!!

; ACL 權限檢查順序如下:

; 1. 檢查使用者不允許的(如果找到穩合的,就決定不允許)

; 2. 檢查使用者允許的(的(如果找到穩合的,就決定允許)

; 3. 看看使用者屬於那些群組

; 4. 檢查群組不允許的(如果找到穩合的,就決定不允許)

; 5. 檢查群組允許的(如果找到穩合的,就決定允許)

; 6. 如果全部都沒找到,則決定不允許


這INI檔可用來定義使用者(ARO)所屬的群組與權限,也可用於定義群組的權限。


譯註:原文要大家去11.4節找更詳細的資料,不過譯者沒找到。乾脆直接把在acl.ini.php檔發現的說明文字放進來讓大家參考。



第三節


定義權限:Cake的資料庫型ACL



開始


ACL權限資料預設存放於資料庫中。資料庫型ACL(或叫dbACL)含有一組核心model,和可由命令列執行的script。
這model用來與資料互動,存放與讀取ACL的樹狀資料。
命令列的script則幫你開個頭,讓你在一開始學習就能和這棵樹互動。



一開始,你必需確定/app/config/database.php有存在,且設定正確。
對於一個剛剛安裝好的Cake系統來說,分辨這件事最容易的方法就是用web流覽器連到安裝目錄。
在這一頁最上方應該會看到"Your database configuration file is present."和"Cake is able to connect to the database."。
如果有錯誤,請參考4.1節,會教您如何設定資料庫。



接著,使用ACL命令列script將資料庫初始化,以便儲存ACL資料。
/cake/scripts/acl.php這支script可以幫助完成這件事。
/cake/scripts/目錄下執行以下的命令:


使用acl.php將資料庫初始化


$ php acl.php initdb



Initializing Database...

Creating access control objects table (acos)...

Creating access request objects table (acos)...

Creating relationships table (aros_acos)...



Done.



此時,在這個專案的資料庫中應該可以看到新的資料表。
如果你對Cake建立的樹狀資料感到好奇,可以打開資料庫看個清楚。
基本上,它存放的是各節點與節點在樹中的位置。
而acos和aros資料表則存放與他們相關的節點,aros_acos資料表則將aros和acos連結起來。



現在,你可以開始建立自己的ARO和ACO樹了。



建立ARO和ACO


有二種方法取用某個ARO或ACO。
其一是指定一個數字的id,而這個數字通常就是資料表的主鍵。
另一個方法是指定一個字串別稱。
這二種方法並不是互斥的。



建立ARO的方法是使用Aro model裡的方法。
Aro類別的create()方法有三個參數:$link_id,$parent_id,和$alias。
這個方法會在$parent_id下建立新的ACL物件,如果$parent_id是null,則表示這是個根物件。
$link_id則可以將使用者物件連結到ACL結構內。
$alias則可以讓你透過別名取用ARO物件,而不是沒意義的數字。


在建立ACO和ARO之前,必需先載入這些類別。
最簡單的方法是在controller裡使用$components陣列把ACL component包含進來使用:


var $components = array('Acl');

完成之後,讓我們看看建立這些物件的程式看起來是什麼樣子。
以下的程式碼可以放在controller action的任何地方:


$aro = new Aro();



// 首先,建立幾個ARO

// 這些物件的父層一開始並沒有東西



$aro->create( 1, null, 'Bob Marley' );

$aro->create( 2, null, 'Jimi Hendrix');

$aro->create( 3, null, 'George Washington');

$aro->create( 4, null, 'Abraham Lincoln');



// 現在,建立幾個群組將這些使用者組織起來:

// 注音,這些物件的ID是0,因為他們永遠不會代表系統內任何一個使用者。



$aro->create(0, null, 'Presidents');

$aro->create(0, null, 'Artists');



//再來,把所有的ARO與相對的群組連起來:



$aro->setParent('Presidents', 'George Washington');

$aro->setParent('Presidents', 'Abraham Lincoln');

$aro->setParent('Artists', 'Jimi Hendrix');

$aro->setParent('Artists', 'Bob Marley');



//簡而言之,建立ARO的方法如下:

$aro = new Aro();

$aro->create($user_id, $parent_id, $alias);

你也可以在命令列模式下用$acl.php create aro <link_id> <parent_id>
<alias>
這個script建立ARO。


ACO的建立方法也類似:


$aco = new Aco();



//建立一些ACO物件

$aco->create(1, null, 'Electric Guitar');

$aco->create(2, null, 'United States Army');

$aco->create(3, null, 'Fans');



// 要為這些物件建立群組,可以使用setParent(),在這個範例如就不示範了。



//所以,建立ACO的方法為:

$aco = new Aco();

$aco->create($id, $parent, $alias);

命令列模式下的script:


$acl.php create aco <link_id> <parent_id>
<alias>




指定權限


建立ACO和ARO後,我們終於可以開始指定二個群組間的權限了。
負責做這件事的,是Cake的核心Acl component。
繼續我們剛剛的範例:


// 首先,我們必需在controller裡使用Cake的ACL component



class SomethingsController extends AppController

{

    // 宣告對Acl component的使用權



    var $components = array('Acl');



    // 記得:ACL在沒有任何資訊的情況下,預設是拒絕所有的事。

    // 所有的存取動作都會被禁止。讓我們對ARO開啟一些對ACO的

    // 存取權限。



    function someAction()

    {

        // 允許



        // 這兒是給予ARO對ACO完整控制權的地方

        $this->Acl->allow('Jimi Hendrix', 'Electric Guitar');

        $this->Acl->allow('Bob Marley',   'Electric Guitar');



        // 我們也可以對群組指配權限,記得嗎?

        $this->Acl->Allow('Presidents', 'United States Army');



        // allow()方法其實有第三個參數,$action。

        // 可以使用這個參數只指定部分存取功能。

        // $action可以設成create, read, update 或 delete。

        // 如果沒有指定,則假設全部一起指定。



        $this->Acl->allow('George Washington', 'Electric Guitar', 'read');

        $this->Acl->allow('Abraham Lincoln',   'Electric Guitar', 'read');



        // 拒絕



        // 設定拒絕的方法和上面類似:

        $this->Acl->deny('Abraham Lincoln', 'United States Army');





    }

}

 

這麼一個特殊的範例也許沒什麼特別的功用,但它可以向您展示整個流程。
把Acl component和使用者管理的controller合在一起使用最有用。
當系統建立了一個使用者,他的ARO可以同時被建立,並放在正確的節點上。
接著依他的狀況將權限設到某個ACO或ACO群組上。


權限也可以在命令列下透過script指派。
語法和model裡的函式類似,若實在不懂,直接執行$php acl.php help也會列出使用方法。




第四節


檢查權限:ACL Component


檢查權限是使用Cake ACL裡最簡單的一部分:只有一個函式,check()。
在AppController的某個地方進行ACL檢查是個不錯的主意,只要放在那兒,
就可以在應用程式的任何地方進行權限檢查。下面的個範例:


class AppController extends Controller

{

    // 取得component

    var $components = array('Acl');



    function checkAccess($aco)

    {

        // 使用component檢查權限

        $access = $this->Acl->check($this->Session->read('user_alias'), $aco, $action = "*");



        //拒絕存取

        if ($access === false)

        {

            echo "access denied";

            exit;

        }

        //允許存取

        else

        {

            echo "access allowed";

            exit;

        }

    }

}

基本上,只要讓Acl component在AppController裡可以使用,應用程式的其他地方就都可以使用。


// 這是基本的呼叫法:

$this->Acl->Check($aro, $aco, $action = '*');


CakePHP使用手冊-插件(Plugin)

轉貼自 http://www.ezluk.org/

插件(Plugin)



CakePHP允許您將一堆model,controler和view打包在一起,讓別人以plugin的方式使用在自己的CakePHP應用程式裡。
有一個很棒的使用者管理模組?簡單的blog?或是好用的web service模組?將它們打包成CakePHP plugin,放到別人的應用程式裡吧。



應用程式和安裝的plugin間最主要的連繫在於應用程式的設定(資料庫連結設定等)。
除此之外,它在自己的小空間內運作,就好像只有自己是獨立的應用程式一樣。



第一節


建立Plugin



讓我們示範建立一個新的plugin,功能是訂pizza。還有什麼功能比這個範例更有用的呢?
開始吧,我們必需先在/app/plugins目錄內建立一個子目錄,準備將plugin 的檔案放在裡頭。
這個子目錄的名稱相當重要,會被用在很多地方,所以選一個好名字吧。
對這個範例來說,就讓它叫'pizza'好了。
最後目錄結構看起來會像這樣:




定Pizza plugin的目錄結構



/app
/plugins
/pizza
/controllers <- plugin controllers 放這兒
/models <- plugin models 放這兒
/views <- plugin views 放這兒
/pizza_app_controller.php <- plugin的 AppController,依據plugin的名字命名
/pizza_app_model.php <- plugin的 AppModel,依據plugin的名字命名



一般的應用程式不需要定義AppController和AppModel,但是plugin需要。
必需建立它們,plugin才會正常運作。
這二個特殊的類別是根據plugin的名字來命名,類別繼承自AppController和AppModel類別。
它們看起來像這樣:




Pizza Plugin AppController:
/app/plugins/pizza_app_controller.php



<?php



class PizzaAppController extends AppController

{

    //...

}



?>




Pizza Plugin AppModel: /app/plugins/pizza_app_model.php



<?php



class PizzaAppModel extends AppModel

{

    //...

}



?>



如果你忘了定義這二個特別的類別,CakePHP會送你一個"Missing Controller"錯誤。




第二節


Plugin的Controller



我們這個pizza plugin的controller會存放在/app/plugins/pizza/controllers
既然我們主要想追踪的是pizza訂單,那就得要有一個OrdersController。




雖然不是絕對必要,但我們還是強烈建議,plugin裡的controller最好取相對唯一的名稱,以免與使用的應用程式相衝。
其他程式內也非常可能會用UsersController,OrderController或ProductController等名稱:
所以你對controller的命名可能需要多一點創意,或把plugin的名稱當作類別的前置詞(像PizzaOrdersController)。




所以,我們把新的PizzaOrdersController放在/app/plugins/pizza/controllers裡,看起來像這樣:




/app/plugins/pizza/controllers/pizza_orders_controller.php



<?php



class PizzaOrdersController extends PizzaAppController

{

    var $name = 'PizzaOrders';



    function index()

    {

        //...

    }



    function placeOrder()

    {

        //...

    }

}



?>



注意這個controller是繼承plugin的AppController(叫PizzaAppController)而不是上層應用程式的AppController。




第三節


Plugin的Model



plugin的Model存放在/app/plugins/pizza/models目錄內。
我們已經為這個plugin定義了一個PizzaOrdersController,讓我們為這個controller建一個model,叫PizzaOrder(
類別名稱PizzaOrder有依我們的命名規則命名,也夠獨特,所以就讓它叫這個名字吧)。




/app/plugins/pizza/models/pizza_order.php



<?php



class PizzaOrder extends PizzaAppModel

{

    var $name = 'PizzaOrder';

}



?>



同樣的,這個類別繼承自PizzaAppModel而不是AppModel。




第四節


Plugin的View



View的行為和一般的應用程式一模一樣。只要將他們放在/app/plugins/[plugin]/views/目錄內。
對我們這個訂pizza的plugin來說,最少需要一個view對應PizzaOrdersController::index() action,檔名和目錄位置像這樣:




/app/plugins/pizza/views/pizza_orders/index.thtml



<h1>Order A Pizza</h1>

<p>Nothing goes better with Cake than a good pizza!</p>

<!-- An order form of some sort might go here....-->




第五節


使用plugin



現在你已經備妥一切,可以準備發布(這時,我們會建議再多一些額外的資料,如說名檔,SQL檔等)。



plugin被安裝在/app/plugins後,就可以透過URL /pluginname/controllername/action存取。
在訂pizza的範例中,就可以在/pizza/pizzaOrders 存取到PizzaOrdersController。



以下是在CakePHP中使用plugin的一些注意事項:





  1. 如果[Plugin]AppController和[Plugin]AppModel不存在,在嘗試存取plugin controller時,
    會得到"Missing Controller"的錯誤訊息。





  2. 可以用plugin的名字做一個預設的controller。
    如果有做這個controller,就可以透過/[plugin]/action存取。
    例如,有個叫'users'的plugin,內含名為UsersController的controller,就可以透過/users/add取用add這個action。
    但要確定沒有另一個叫AddController controller被放在[plugin]/controllers目錄內。


    譯註:存取users plugin的AddController的URL也是/users/add/[action]





  3. Plugin預設使用/app/views/layouts目錄下的layout。





  4. 可以在controller內使用$this->requestAction('/plugin/controller/action');與plugin進行內部溝通。




  5. 使用你使用requestAction,請確認controller和model名稱盡可能唯一。
    否則PHP就會送你一個"redefined class ..."的錯誤。





特別感謝Felix Geisendorfer提供本章節的內容。


CakePHP使用手冊-資料檢驗

轉貼自 http://www.ezluk.org/

資料檢驗



第一節


資料檢驗



建立自訂的資料檢驗規則可以協助確認Model裡資料是否合乎企業邏輯的需求,
例如密碼長度只能八個字元,使用者名稱字能使用文字等等。



資料檢驗的第一步是在Model裡建立檢驗規則。
這件事可透過定義Model裡的Model::validate陣列達成,例如:




/app/models/user.php



<?php

class User extends AppModel

{

   var $name = 'User';



   var $validate = array(

      'login' => '/[a-z0-9\_\-]{3,}$/i',

      'password' => VALID_NOT_EMPTY,

      'email' => VALID_EMAIL,

      'born' => VALID_NUMBER

   );

}

?>



檢驗規則定義法是使用Perl相容的通用表示法,有些常用的規則已事先定義在/libs/validators.php。如:




  • VALID_NOT_EMPTY


  • VALID_NUMBER


  • VALID_EMAIL


  • VALID_YEAR



若model定義了$validate陣列,檢驗動作便會在資料儲存前自動啟動(呼叫Model::save()時)。
若想要手動啟動檢驗功能,
也可以直接呼叫Model::validates()(如果資料錯誤會傳回false)和Model::invalidFields()(傳回存有錯誤訊息的陣列)。



但通常資料都隱藏在controler的程式裡。
下面的範例示範如果使用檢驗的機制:




/app/controllers/blog_controller.php 內處理表單資料的Action



<?php

class BlogController extends AppController {



   var $uses = array('Post');



   function add ()

   {

      if (empty($this->data))

      {

         $this->render();

      }

      else

      {

         if($this->Post->save($this->data))

         {

             //太好了,資料合乎規則

         }

         else

         {

            //危險,威爾羅賓遜!檢驗結果錯誤。

            $this->set('errorMessage', 'Please correct errors below.');

            $this->render();

         }

      }

   }

}

?>




這個action使用的view看起來可以像這樣:





在/app/views/blog/add.thtml加入表單的view


<h2>Add post to blog</h2>

<form action="<?php echo $html->url('/blog/add')?>" method="post">

    <div class="blog_add">

        <p>Title:

            <?php echo $html->input('Post/title', array('size'=>'40'))?>

            <?php echo $html->tagErrorMsg('Post/title', 'Title is required.')?>

        </p>

        <p>Body

            <?php echo $html->textarea('Post/body') ?>

            <?php echo $html->tagErrorMsg('Post/body', 'Body is required.')?>

        </p> 

        <p><?=$html->submit('Save')?></p>

    </div>

</form>

         



Controller::validates($model[, $model...])可用來啟動model裡自訂的檢驗規則。
Controller::validationErrors()則傳回model丟出的錯誤訊息,然後用tagErrorMsg()顯示於view內。



如果你想要設計些正規表示法無法表示的檢驗規則,可以使用model的invalidate()函式將某一欄位標示為錯誤。
例如我們想要在使用者要建立的使用者名稱已存在時,在表單上顯示錯誤訊息。
由於單單使用正規表示法很難表示這樣的規則,我們必需自己另外設計這個邏輯,接著把這個欄位標示為錯誤,
再經由Cake一般處理的流程處理。controller看起來像這樣:



<?php



class UsersController extends AppController

{

    function create()

    {

        // 來查是否有提交表單資料

        if (!empty($this->data['User']))

        {

            //看看這位使用者的姓名是否存在

            $user = $this->User->findByUsername($this->data['User']['username']);



            // 將欄位標示為錯誤,觸發HTML Helper的錯誤訊息。

            if (!empty($user['User']['username']))

            {

               //產生tagErrorMsg('User/username')

               
$this->User->invalidate('username');

            }



            //試著儲存資料,如果有錯就不要做。

            if($this->User->save($this->data))

            {

                $this->redirect('/users/index/saved');

            }

            else

            {

                 $this->render();

            }

        }

    }

}



?>

 

CakePHP使用手冊-全域函式與常數

轉貼自 http://www.ezluk.org/

全域函式與常數


本章列出一些使用Cake開發應用程式時常用到的全域函式與常數。



第一節


全域函式



這兒列出的是Cake裡每個地方都可以使用的函式。
其中有很多是為了包裝名字很長的PHP函式而設計(包裝型函式),當你想要短小精幹的函式為你重覆做一些事,那這就是你要的。
還有些(像vendor()和uses())可以用來引用(include)外部程式碼,或執行其他函式。


譯註:接下來會用"包裝型函式"代表Wrapper,此類的函式內容就是把所有的參數轉去呼叫另一個函式,
主要目的是減短函式名稱。




  • config


載入Cake的核心設定檔,如果成功的話就傳回true。



  • uses


  • string $lib1


  • string $lib2...




用來載入Cake的核心函式庫(放在cake/libs/)目錄內)。
用不含副檔名'.php'的函式庫檔名指定。



uses('sanitize', 'security');



  • vendor


  • string $lib1


  • string $lib2...




載入第三方函式庫(放在/vendors目錄內)。
用不含副檔名'.php'的函式庫檔名指定。



vendor('myWebService', 'nusoap');



  • debug


  • mixed $var


  • boolean $showHtml = false




如果應用程式的DEBUG層級不是0,就把$var字串印出。
如果$showHtml是true,URL資料會以流覽器視為字串的格式輸出。


譯註:如果$showHtml是true,'<'為被以'%lt;'取代,'>'會以’%gt;'取代。




  • a


傳回包裝型函式使用的參數陣列。


譯註:原始碼中的註解為:傳回內容存著傳入參數的陣列。例如: a('a', 'b')傳回 array('a', 'b')。



function someFunction()

{

    echo print_r(a('foo', 'bar'));

}



someFunction();



// output:



array(

    [0] => 'foo',

    [1] => 'bar'

)




  • aa






傳回包裝型函式使用的關聯式陣列


譯註:原始碼中的註解為:由傳入的參數建立關聯式陣列。例如:aa('a','b')傳回 array('a'=>'b')。



echo aa('a','b');


// 輸出:


array(

    'a' => 'b'

)




  • e


  • string $text




ehco()函式的包裝型函式。





  • low






strtolower()函式的包裝型函式。





  • up






strtoupper()函式的包裝型函式。





  • r


  • string $search


  • string $replace


  • string $subject




str_replace()函式的包裝型函式。





  • pr


  • mixed $data




便利的函式,功能和下列的程式相同:



echo "<pre>" . print_r($data) . "</pre>";

只有在DEBUG設為非零時才會把資料印出。





  • am


  • array $array1


  • array $array2...




將傳入的所有陣列結合成一個陣列。





  • env


  • string $key




由可用的管道取得環境變數。這個函式是準備在$_SERVER或$_ENV被關閉時使用的。



這函式還會負責在Server不支援時,模擬PHP_SELF和DOCUMENT_ROOT。
事實上,最好都用env()取代$_SERVER或getenv()(特別是如果你想要開放程式給別人用),因為他會自動模擬所有的狀況。





  • cache


  • string $path


  • string $expires


  • string $target = 'cache'




把$data的資料存放在CACHE/$path目錄內作為快取,CACHE預設為/app/tmp/。
$expires裡放的時間字串格式必需是strtotime()能接受的格式。
$target則可以是'cache'或'public'。


譯註:'public'時則暫存在WEB_ROOT/$path/目錄下。



  • clearCache


  • string $search


  • string $path = 'views'


  • string $ext




清除快取目錄內的檔案及子目錄。



若$search是字串,則名稱和他相同的目錄或檔名就會被由快取目錄裡移除。
$search還可以是陣列,將多組字串放在陣列中一次指定,便可一次刪除多個檔案或目錄。
如果$search內容是空的,則/app/tmp/cache/views/ 就會被清空。



$path參數用來指定要刪除的檔案與目錄放在/tmp/cache/裡,那個目錄裡。
預設值是'views',所以預設會去/app/tmp/cache/views/目錄內找檔案刪除。



$ext則用來指定要刪除檔案的副檔名。





  • stripslashes_deep


  • array $array




將陣列內所有元素的斜線('/')去除。



  • countdim


  • array $array




計算$array的維度。看是一維陣列,二維陣列...n維陣列。



  • fileExistsInPath


  • string $file




到include_path所指定的各目錄中找尋$file,如果找到則傳回路徑,找不到則傳回false。





  • convertSlash


  • string $string




把正斜線('/')換成底線('_'),若字串中第一個和最後一個字元是底線,則將它刪除。




第二節


CakePHP核心定義常數



ACL_CLASSNAME:指定目前Cakephp使用中的ACL類別名稱。
這個常數讓使用者用於整合第三方類別。



ACL_FILENAME:ACL_CLASSNAME指定的類別存放的檔名。



譯註:ACL 是Access Control List的縮寫,用於控制存取權限。




AUTO_SESSION:如果設成false,則在發出request時,程式不會自動呼叫session_start()。



CACHE_CHECK:如果設成false,會將整個應用程式中view的快取功能關閉。



CAKE_SECURITY:指定session的安全等級,CAKE_SESSION_TIMEOUT會跟者改變。
此值可以是低:'low',中:'medium',高:'high'。
依不同設定,CAKE_SESSION_TIMEOUT會被乘上一個值:





  1. low: 300





  2. medium: 100





  3. high: 10





CAKE_SESSION_COOKIE:應用程式使用的session cookie名稱。



CAKE_SESSION_SAVE:可以設成'php','file'或'database'。





  1. php:Cake使用PHP預設方式處理session(通常定義在php.ini中)。





  2. file:Session的資料會被存放在/tmp中。





  3. database: 使用Cake的session資料庫管理機制處理(請參考"Cake Session Component"一章)。





CAKE_SESSION_STRING:session管理時使用的亂數字串。



CAKE_SESSION_TABLE:存放session資料的資料表(如果CAKE_SESSION_SAVE被設成'database'時)。
如果預設的資料庫連線有設定資料表名稱前置詞,在此就不要再包含它了。



CAKE_SESSION_TIMEOUT:session過期的時間。這個值會再依CAKE_SECURITY被乘上一個值。



COMPRESS_CSS:如果設成true,CCS風格表將在輸出時被壓縮。
要啟動這個功能,必需讓web伺服器有寫入/var/cache 目錄的權限。
使用時,使用/ccss 風格表(不再是/css),或直接使用Controller::cssTag()。



DEBUG:定義CakePHP應用程式執行時,錯誤訊息回報層級。值由0到3:





  1. 0:產品模式。不輸出位何錯誤訊息和除錯訊息。





  2. 1:開發模式。警告,錯誤與除錯訊息都顯示。





  3. 2:和1一樣,不同的是以SQL指令輸出。





  4. 3:和2一樣,但會把目前物件的內容都下來(通常是controller)。





LOG_ERROR:錯誤常數。用來辨別記錄與除錯訊息。目前PHP支援LOG_DEBUG。



MAX_MD5SIZE: 執行md5()使用的最大資料量(bytes)。



WEBSERVICES: 如果設成true,將啟動Cake內建的webservices功能。




Section 3


CakePHP 路徑常數



APP:應用程式目錄的路徑。



APP_DIR:應用程式目錄的名稱。



APP_PATH:應用程式中app目錄的絕對路徑。



CACHE:快取檔目錄所在路徑。



CAKE:應用程式的cake目錄所在路徑。



COMPONENTS:應用程式的compoents目錄路徑。



CONFIGS:設定檔目錄的路徑。



CONTROLLER_TESTS:controller測試目錄的路徑。



CONTROLLERS:應用程式的controller所在路徑。



CSS:CSS檔目錄的路徑。



ELEMENTS:element目錄的路徑。



HELPER_TESTS:helper測試目錄的路徑。



HELPERS:helper目錄的路徑。



INFLECTIONS:inflactions目錄的路徑(通常在設定目錄裡)。



JS:JavaScript檔存放目錄的路徑。



LAYOUTS:layout存放目錄的路徑。



LIB_TESTS:Cake函式庫測試目錄的路徑。



LIBS:Cake函式庫目錄的路徑。



LOGS:記錄檔存放目錄的路徑。



MODEL_TESTS:model測試目錄的路徑。



MODELS:model目錄的路徑。



SCRIPTS:Cake script目錄的路徑。



TESTS:測試目錄的路徑(model,controller等測試目錄的父目錄)。



TMP:tmp目錄的路徑。



VENDORS:vendors目錄的路徑。



VIEWS:view目錄的路徑。




第四節


CakePHP Webroot 設定路徑



CORE_PATH:Cake核心函式庫路徑。



WWW_ROOT:應用程式的webroot目錄的路徑。



CAKE_CORE_INCLUDE_PATH:Cake核心函式庫路徑。



ROOT:CakePHP最基底的index.php所在的目錄。



WEBROOT_DIR:應用程式的webroot目錄路徑。


CakePHP使用手冊-AJAX Helper

轉貼自 http://www.ezluk.org/

第二節



AJAX Helper



Cake的Ajax helper使用最流行的Prototype和script.aculo.us二大函式庫控制Ajax與客戶端特效。
所以,為了要使用這個helper,你必需從http://script.aculo.us下載最近的版本,放在/app/webroot/js/
另外,想使用Ajax helper的view還必需把這些函式庫包含進去。



這helper裡大部分函式都需要一個特別的陣列參數,$options。
$options用來指定Ajax操作中使用的各種參數。以下說明可以指定的值:




AjaxHelper $options 參數



/* 一般選項 */



$options['url']         // 這個動作要呼叫的URL。



$options['frequency']   // remoteTimer()或observeField()呼叫的間隔秒數。



$options['update']      // 根據Ajax操作結果進行更新的元素的DOM ID。



$options['with']        // 和Ajax表單提交時一併傳送和serialize的表單

                        // 元素的DOM ID。



$options['type']        // 設定值是'asynchronous'(預設)和'synchronous'

                   
    // 其中之一。可選擇操作模式。


/* 回呼函式 : XMLHttpRequest執行過程中,特定時間點所執行的JS 程式碼。*/



$options['loading']     // 流覽器將遠端文件載入時執行的JS 程式碼。



$options['loaded']      // 流覽器將遠端文件載入完成時執行的JS 程式碼。



$options['interactive'] // 當使用者可以和遠端文件互動時執行的程式碼,

                   
    // 即使還沒完全載入。

   

$options['complete']    // XMLHttpRequest完成時執行的JS 程式碼。



$options['confirm']     // XMLHttpRquest動作開始前的確認對話框顯示的文字。



$options['condition']   // XMLHttpRequest初始化前需要符合的JS 條件。



$options['before']      // request初始前呼叫的JS程式碼。



$options['after']       // 在request初始化完成之後,文件載入之前執行的JS程式。



以下是讓Ajax在Cake中既快又容易的幾個helper的函式:





  • link


  • string $title


  • string $href


  • array $options


  • boolean $confirm


  • boolean $escapeTitle




建立一個取回位於$options['url']的連結,標題使用$title,完成時更新設定的DOM元素。
這函式可以使用所有的回呼函式。





  • remoteFunction


  • array $options




這函式產生執行遠端呼叫所需的JavaScript。
主要當成linkToRemote的helper。
除非需要產生一些特別的script,否則很少用到。





  • remoteTimer


  • array $options




定期呼叫$options['url']指定的動作,時間間隔由$options['frequency']定義,單位為秒,預設為10秒。
通常使用於用遠端呼叫的結果更新特定的div(由$options['update']指定)。
這函式可以使用所有回呼函式。





  • form


  • string $action


  • string $type


  • array $options




傳回可以提交至$action的表單標籤,
透過XMLHttpRequest在背景執行可以免除傳統POST需要重新載入的問題。
這樣子傳回的表單資料和一般的方法都一樣(在controller中用$this->params['form']取用)。
接者根據操作結果進行更新$options['update']指定的DOM 元素。
這函式可以使用所有的回呼函式。





  • observeField


  • string $field_id


  • array $options




每$options['frequency']秒檢查一次由$field_id指定的DOM ID代表的欄位,
一旦發現內容有變化,馬上呼叫$options['url']裡的action。
可以更新$options['update']指定的DOM 元素,或由$options['with']指定一個表單元素。
這函式可以使用所有的回呼函式。





  • observeForm


  • string $form_id


  • array $options




和observeField()用途相同,只是它監視的是表單裡所有的元素。





  • autoComplete


  • string $field


  • string $url


  • array $options




產生ID為$field的文字欄文,內具自動完成功能。
$url所指的action應該可以傳回自動完成的字串:
基本上,這action要把一堆由<ul></ul>包起來,未經排序的自動完成字串分開。
如果要讓有自動完成功能的欄位取得blog文章的標題,controller的action看起來會像這樣:



function autocomplete ()

{

    $this->set('posts',

        $this->Post->findAll(

            "subject LIKE '{$this->data['Post']['subject']}'")

        );

    $this->layout = "ajax";

}


然後autocomplete()呼叫的view看起來會像這樣:



<ul>

<?php foreach($posts as $post): ?>

<li><?php echo $post['Post']['subject']; ?></li>

<?php endforeach; ?>

</ul>


實際涵有這種欄位的view,程式碼會像這樣:



<form action="/users/index" method="POST">

    <?php echo $ajax->autoComplete('Post/subject', '/posts/autoComplete')?>

    <?php echo $html->submit('View Post')?>

</form>


autoComplete函式會將這個資訊輸入到文字欄位內,而action所提供的自動完成字串則會被顯示在某些div上。
也可以如下例一般設定這個view的風格:



<style type="text/css">



div.auto_complete {

    position         :absolute;

    width            :250px;

    background-color :white;

    border           :1px solid #888;

    margin           :0px;

    padding          :0px;

}



li.selected { background-color: #ffb; }



</style>




  • drag


  • string $id


  • array $options




讓$id指定的DOM物件可以被拖移。
這函式的$options多了一些額外的參數:



// (版本變號請查script.aculo.us)



$options['handle']     // (v1.0)元素內handle等於設定值的子元素才能被

                   
   // 拖移。這個值必需是元素的參考或id。



$options['handle']     // (V1.5) 功能和上面一樣,除了變成可以設成CCS class。

                   
   // 在元素內的子元素中,第一個屬於這個CCS class的,

                   
   // 會被當成handle。



$options['revert']     // (V1.0) 如果設成true,元素會被拖移結束後回到原位。



$options['revert']     // (V1.5) Revert變成也可以是拖移結束後呼叫的函式參考。



$options['constraint'] // 如果設成'horizontal'或'vertical',拖移的方向會被限

                   
   // 制在水平方向或垂直方向。




  • drop


  • string $id


  • array $options




讓$id所指的DOM元素可以把被可拖移元素放置進去。同樣的,也有一些額外的參數,說明如下:



$options['accept']      // 設定成敍述CCS class的字串或內含字串的Javascript

                   
    // 陣列。只允許屬於這些CCS class的可拖移元素被放置

                   
    // 進去。



$options['containment'] // 可放置的元素只會接受放入在列表中的元素(或元素id)

                   
    // 這個設定值可以是一個元素或多個元素的JavaScript

                        // 陣列.



$options['overlap']     // 如果設成horizontal(水平)或vertical(垂直),則只有在

                   
    // 設定方向上重疊一半以上時才會被放置進去。






  • dropRemote


  • string $id


  • array $options


  • array $ajaxOptions




建立可放置的元素,當有元素被放置在時立即產生XMLHttpRequest。
$options跟drop()的一樣。$ajaxOptions的定義和一般的$options沒二樣。


譯註:找了原始碼後發現,$ajaxOptions會被原封不動的傳入remoteFunction()中,
而remoteFunction的傳入值正是一般常見的$options。


sortable


  • string $id


  • array $options




讓一組浮動的物件(由$id指定DOM元素ID)可排列。
$options 陣列可以把排列方法設定如下:



$options['tag']         // 設定容器內的子元素中屬於這種標籤的才能被排列。

                   
    // 對UL和OL容器來說,值是LI。其他種子元素則必須指定,

                   
    // 預設是LI。



$options['only']        // 進一步限制只擇選屬於這個CCS class的子元素為可排列(如

                   
    // 果設定的是一個內含字串的陣列,則可指定指定多種CCS

                   
    // class)。



$options['overlap']     // 不是vertical(垂直,預設)就是horizontal(水平)。 對

                   
    // 浮動的或水平列表,選horizontal。重直列表選vertical。



$options['constraint']  // 把可拖移元素的移動方向限制在垂直(vertical)或水平

                        // (horizontal)方向上。.



$options['containment'] // 讓可排列的元素間可以拖放。設定值是元素或元素ID的陣列,

                   
    // 當然是指容器內的元素。



$options['handle']      // 用handle屬性建立打拖移元素,handle屬性請看drag()

                        // 的敍述。

 




  • editor


  • string $id


  • string $url


  • array $options




使用DOM id為$id的元素建立嵌入型編輯器。
這種編輯器不在編輯模式時時會變形成一排文字,滑鼠過去時會亮起來,按下去會進入編輯模式,隨即放大成一般編輯元素的編輯器。
第二個參數是當按下確定時,資料被傳送的URL。
嵌入型編輯器更詳細的資料可以在此找到
Script.aculo.us
wiki.




CakePHP使用手冊-Helper

轉貼自 http://www.ezluk.org/

第三節



Javascript



JavaScript helper用於協助開發者透過關鍵的資訊,產生完整格式的JavaScript標籤和資料。

譯註:例如,只需提供edit.js檔名,即可使用link()完成
<script type="text/javascript" src="edit.js"></script>
完整的 HTML 字串。





  • codeBlock


  • string $string




將$string的字串包在JavaScript的<script>標籤內傳回。





  • link


  • string $url




把本機內的JavaScript連結進來使用。$url是JavaScript的檔名(含.js)


譯註:原始碼中是把$url接上一大堆路徑設定後,當成
<script ></script>的src屬性。





  • linkOut


  • string $url




和link()相同,只是這兒的標籤假設$url所參照的script不同在一個網域內。


譯註:原始碼中直接把$url字串當成
<script ></script>的src屬性。




  • escapeScript


  • string $script




把$script中的換行字元,單引號和雙引號脫逸掉。





  • event


  • string $object


  • string $event


  • string $observer


  • boolean $useCapture




在某個元素上附加事件。配合Prototype函式庫使用。





  • cacheEvents






將event()所建立的JavaScript暫存。





  • writeEvents






將cacheEvents()所暫存的事件寫入。





  • includeScript


  • string $script



將函式庫(例如Prototype函式庫)包含進來使用。
$script是指被包含進來的檔名(不含'.js'),如果是空字串,則表示將 WWW_ROOT/js/ 內所有的檔都包含進來使用。


譯註:include的意思其實就是把某個檔案內容原封不動貼上去。





Number



Number helper含有很多好用的函式可用於在view中加入格式化的字串。





  • precision


  • mixed $number


  • int $precision = 3




以$precision設定的精度將$number傳回。





  • toReadableSize


  • int $sizeInBytes




把$sizeInBytes所指的資料容量大小轉換成KB,MB,GB或TB這種人們可接受的單位傳回。




  • toPercentage


  • mixed $number


  • int $precision = 2




把精度為$presision的$number加上百分比符號後的字串傳回。


譯註:toPercentage(1.23456,2)就傳回'1.23%'。





Text



Text Helper協住關發者將完整格式的文字輸出的流覽器中。





  • highlight


  • string $text


  • string $phrase

  • string $highlighter = '<span
    class="highlight">\1</span>'




將$text中所出現的$phrase字串用$highlighter所提供的HTML標籤包起來。





  • stripLinks


  • string $text




將$text中所有的HTML連結(<a href= ...)去除後傳回。





  • autoLinkUrls


  • string $text


  • array $htmlOptions




在$text中找到類似http://或ftp://等字串後,加入(<a href=....)的標籤。


譯註:原文太簡化,這段文字是從原始碼中找到的,由於這函式內部會使用到HTML helper,$htmlOptions的說明可以參考HTML Help。





  • autoLinkEmails


  • string $text


  • array $htmlOptions




把$text字串加上email標籤(<a href="mailto:....)後傳回。


譯註:由於函式內部會使用到HTML helper,$htmlOptions的說明可以參考HTML Help。




  • autoLink


  • string $text


  • array $htmlOptions




把$text內所有URL和email連結轉成HTML標籤傳回。


譯註:由於函式內部會使用到HTML helper,$htmlOptions的說明可以參考HTML Help。





  • truncate


  • string $text


  • int $length


  • string $ending = '...'




將$text的前$length個字接上$ending字串(預設是'...')傳回。





  • excerpt


  • string $text


  • string $phrase


  • int $radius = 100


  • string $ending = '...'




從$text中節錄一小段文字傳回。
程式會在$text中找到$phrase字串,把前$radius到後$radius的字串接上$ending字串後傳回。





  • flay


  • string $text


  • boolean $allowHtml =
    false




將文字以flay格式轉成html,類似Textile或Redcloth,只是語法不同。


譯註:$allowHtml等於false時會把字串中的 '>' 以 '&gt;' 取代, '<' 以 '&lt;' 取代。



Time



Time Helper提供開發者一些函式把Unix的時間與日期字串轉換成看得懂的格式,顯示在流覽器中。



所有函式的$dateString字串,可PHP函式取得,也可由Unix函式取得。





  • fromString


  • string $dateString




將$dateString轉成UNIX時間。傳入的字串可以是UNIX的格式或標準strtotime()傳回的字串。





  • nice


  • string $dateString


  • boolean $return = false




傳回格式很親合的字串。
日期格式為"D, M js Y, H:i",例如 'Mon, Jan 1st 2005, 12:00'。





  • niceShort


  • string $dateString


  • boolean $return = false




傳回的字串格式和nice()一樣,但如果日期是今天,則顯示"Tody, 12:00",若是明天,則顯示"Yesterday, 12:00"。





  • isToday


  • string $dateString




傳回$dateString是否就是今天。





  • daysAsSql


  • string $begin


  • string $end


  • string $fieldName


  • boolean $return = false




傳回用來查詢二個時間點間的資料的SQL字串。





  • dayAsSql


  • string $dateString


  • string $fieldName


  • boolean $return = false




傳回可查詢與$dateString同一天的資料的SQL字串。





  • isThisYear


  • string $dateString


  • boolean $return = false




傳回$dateString是否是今年。





  • wasYesterday


  • string $dateString


  • boolean $return = false




傳回$dateString是否是昨天。





  • isTomorrow


  • string $dateString


  • boolean $return = false




傳回$dateString是否是明天。





  • toUnix


  • string $dateString


  • boolean $return = false




把$dateString字串轉成UNIX的時間。這函式只是把PHP的strtotime()封裝起來而以。



與fromString不同點在於toUnix只能傳入字串,fromString還可以傳入UNIX時間。




  • toAtom


  • string $dateString


  • boolean $return = false




將日期轉為Atom RSS feeds的時間格式。





  • toRSS


  • string $dateString


  • boolean $return = false




將日期轉為 RSS feeds的時間格式。





  • timeAgoInWords


  • string $dateString

  • string $format = 'j/n/y'

  • string $backwards = false

  • string $return = false


  • boolean $return = false




傳回目前時間與$dateString相差的時間或格式化的日期。
$datetime格式必需是像MySQL datetime這種strtotime()看得懂的格式。



譯註:如果相差時間大於一個月,會用"on 2/18/2006"的格式傳回,小於一個月則用"3 weeks, 4 days ago"這種格式傳回。




  • relativeTime


  • string $dateString


  • boolean $return = false




功能和timeAgoInWords()一樣,只是只能使用預設參數。請看timeAgoInWords()說明





  • wasWithinLast


  • string $timeInterval


  • string $dateString


  • boolean $return = false




如果$dateString在$timeInterval的時間內,傳回true,否則傳回false。
$timeInterval要有單位,如'6 hours', '2 days'







第四節


設計自己的Helper



有需要協助產生view程式嗎?如果發現有一小部分的view邏輯不斷的重覆出現,可以設計一個自己的Helper處理這件事。




繼承Helper類別



假設我們要設計一個輸出某種CCS風格的helper。
為了把邏輯裝進Cake既存的Helper結構,你必須建立一個新類別,放在/app/views/helpers目錄裡。
就把我們的Helper叫LinkHelper,實際的php類別看起來像這樣:




/app/views/helpers/link.php



class LinkHelper extends Helper

{

    function makeEdit($title, $url)

    {

        // 建立特殊格式連結的邏輯放這兒...

    }

}



Cake的helper類別內有一些函式可以讓你使用:





  • output


  • string $string


  • boolean $return = false




這函式可以把任何資料傳回view。
AUTO_OUTPUT(請看/app/config/core.php)和$return二個參數決定了傳回資料是要直接輸出到畫面,
還是單純回傳。





  • loadConfig






傳回應用程式目前的核心設定和標籤定義。



讓我們用output()建立標題連結和URL,並將它傳回view。




/app/views/helpers/link.php (加入邏輯)



class LinkHelper extends Helper

{

    function makeEdit($title, $url)

    {

        // 使用helper的output()函式把格式化的資料傳回view

        return $this->output("<div
class=\"editOuter\"><a href=\"$url\"
class=\"edit\">$title</a></div>");

    }

}





呼叫其他的Helper



你可能想用其他既存helper的功能。這時,只要在$helpers 陣列指定需要使用的helper就行了,
使用方法和在controller裡一模一樣。




/app/views/helpers/link.php (使用別的helper)



class LinkHelper extends Helper

{



    var $helpers = array('Html');



    function makeEdit($title, $url)

    {

        // 使用HTML helper輸出格式化資料:

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



        return $this->output("<div class=\"editOuter\">$link</div>");

    }

}





使用自己的Helper



一旦你的helper設計好,並放在/app/views/helpers/目錄後,就可以在controller的$helpers陣列中指定使用了。



class ThingsController

{

    var $helpers = array('Html', 'Link');

}


如果還要使用HTML helper,記得一併放進去。命名規則如下:





  1. LinkHelper = class name





  2. Link = key in helpers array





  3. link.php = name of php file in
    /app/views/helpers.







回饋



請考慮將您的程式回饋回Cake-可以透過我們的Trac系統或email和其中一位開發者連繫,
或者開一個新的CakeForge專案,把你的新helper分享給其他人。



網誌存檔

關於我自己

Aspire freedom , Hope to do Soming make self complete ~