CakePHP – formHelper:checkbox & Model:BeforeValidate()

13Oct09
checkbox

checkbox

Checkboxes 是一組表單組成的, 功能主要是提供一個使用者可多選的項目
用法和 multiple select dropdown 是一樣的
使用那一種表單元素主要是外觀設計的考量
在cakephp 之內, 使用 checkboxes 的code:
</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 1826px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">$form->input('Model.field', array( 'type' => 'select', 'multiple' => 'checkbox' ,'option' => array('1'=>'1','2'=>'2','4'=>'3','8'=>'4') ));</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 1826px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">

從以上的例子可以看到, checkboxes 其實是 select 元素
第二個參數的 ‘option’ 是一個數組, 使用 array(‘值’,'名稱’) 的組合
例子中的值和名稱組合會在下面再詳細解釋
表單提交的數值實際上是一個數組 (可以在controller/views 用debug() 可以看到提交到後台的數組)
但數據庫中卻多數只使用一個欄位儲存 (而且多數是使用int 類)
所以便需要先處理, 再放到數據庫
因為 checkbox 的數值都需要經過 validate
所以需要在 validate 之前先整理 checkbox 的數值
在這個例子中, 數據庫使用一個 int(11) 來儲存一組checkbox 的數值
所以便使用 二進位 數值的表示式
例如, 4 個checkbox 為一組, 它們的數值分別為 2 的倍級, pow(2,0), pow(2,1), pow(2,2), pow(2,3)
所以4個checkbox 的數值分別為 1,2,4,8
如果使用者提交了 第一個和最後一個checkbox, 儲存的數值是: 1+8=9
使用一個 for 迴圈便可以了
</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 1826px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">function beforeValidate() {</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 1826px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">foreach ($this->data['User']['question3'] as $k => $v ) {</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 1826px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">$question3 += $v;</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 1826px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">}</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 1826px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">}</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 1826px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">

注意的是應該只有完成了整個mapping 的程序才 返回 true 或 false
要停止儲存, 返回 false
要繼續儲存, 返回 true
取回它們的數值則較為複雜:
</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 1826px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">$num = 9; //value from DB</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 1826px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">$q = 4; //number answers</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 1826px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">$question3= array();</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 1826px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">for ( $i=1 ; $i<=$q ; $i++ ) {</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 1826px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">if ( $num & pow(2,($i-1)) ) {</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 1826px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">$question3[] = pow(2,($i-1));</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 1826px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">}</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 1826px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">}</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 1826px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">

這個例子示範了 beforeValidate() 和 checkboxes 的組合方法, 但 beforevalidate 其實還有很多很重要的用法
有機會的話再深入研究
@cakephp 1.2.3.8166
BeforeValidate() and checkboxes
Checkboxes is a group of form element that users can select multiple values.
It’s usage is the same as a multiple select downdown, so site owners can use one of them which fits its implementation
Within cakephp, the statement that generate checkboxes is:
</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 1826px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="font-family:courier;color:#cc3300;"><span style="font-size:x-small;"><span style="margin-right:0;margin-left:0;color:#4444cc;">$form</span><span style="margin-right:0;margin-left:0;color:#337733;">-></span><span style="margin-right:0;margin-left:0;color:#4444cc;">input</span><span style="margin-right:0;margin-left:0;color:#337733;">(</span><span style="margin-right:0;margin-left:0;color:#cc3300;">'Model.field'</span><span style="margin-right:0;margin-left:0;color:#337733;">, array( </span><span style="margin-right:0;margin-left:0;color:#cc3300;">'type' </span><span style="margin-right:0;margin-left:0;color:#337733;">=> </span><span style="margin-right:0;margin-left:0;color:#cc3300;">'select'</span><span style="margin-right:0;margin-left:0;color:#337733;">, </span><span style="margin-right:0;margin-left:0;color:#cc3300;">'multiple' </span><span style="margin-right:0;margin-left:0;color:#337733;">=> </span><span style="margin-right:0;margin-left:0;color:#cc3300;">'checkbox' ,'option' => array('1'=>'1','2'=>'2','4'=>'3'<span style="margin-right:0;margin-left:0;color:#cc3300;">,'8'=>'4'<span style="margin-right:0;margin-left:0;color:#cc3300;">) </span><span style="margin-right:0;margin-left:0;color:#337733;">));</span></span></span></span></span></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 1826px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">

which is a select element.
the option array is array(‘value’,'label’)
i will explain the meaning of numbers there in a few rows below
The value that being submitted after pressing submit is an array.
so developers probably want to treak the array before store that into DB.
we can use beforeValidate() callback here.
</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 1826px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">function beforeValidate() {</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 1826px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">//code here</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 1826px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">}</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 1826px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">

As there may be some validation rules on those checkboxes, we have to handle the values before it actually validates.
In my case, I use a int(11) field to store it, using binary represenation.
Example, there are 4 checboxes in the group, they will be assigned as value 1, 2, 4, 8, which is the power of 2.
So if the user submit with first and last option checked, the value to store is 1+8=9. just a for loop will to the track
</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 1826px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">function beforeValidate() {</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 1826px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">foreach ($this->data['User']['question3'] as $k => $v ) {</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 1826px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">$question3 += $v;</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 1826px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">}</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 1826px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">}</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 1826px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">

please note that do not return unless you think the validation can exit (only when validation finished or validation is halt)
return false to stop save,
return true to continue
Retieve them is a little bit tricky, we have to use bit operations
</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 1826px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">$num = 9; //value from DB</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 1826px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">$q = 4; //number answers</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 1826px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">$question3= array();</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 1826px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">for ( $i=1 ; $i<=$q ; $i++ ) {</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 1826px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">if ( $num & pow(2,($i-1)) ) {</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 1826px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">$question3[] = pow(2,($i-1));</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 1826px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">}</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 1826px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">}</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 1826px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">

This example demo the combination of beforeValidate() and checkboxes, but beforeValidate() actually have more important use. Let’s discuss it later.
@cakephp 1.2.3.8166
Checkboxes 是一組表單組成的, 功能主要是提供一個使用者可多選的項目
用法和 multiple select dropdown 是一樣的
使用那一種表單元素主要是外觀設計的考量
在cakephp 之內, 使用 checkboxes 的code:
$form->input('Model.field',
  array( 
    'type' => 'select', 
    'multiple' => 'checkbox' ,
    'option' => array('1'=>'1','2'=>'2','4'=>'3','8'=>'4')
   )
);

從以上的例子可以看到, checkboxes 其實是 select 元素
第二個參數的 ‘option’ 是一個數組, 使用 array(‘值’,'名稱’) 的組合
例子中的值和名稱組合會在下面再詳細解釋
表單提交的數值實際上是一個數組 (可以在controller/views 用debug() 可以看到提交到後台的數組)
但數據庫中卻多數只使用一個欄位儲存 (而且多數是使用int 類)
所以便需要先處理, 再放到數據庫
因為 checkbox 的數值都需要經過 validate
所以需要在 validate 之前先整理 checkbox 的數值
在這個例子中, 數據庫使用一個 int(11) 來儲存一組checkbox 的數值
所以便使用 二進位 數值的表示式
例如, 4 個checkbox 為一組, 它們的數值分別為 2 的倍級, pow(2,0), pow(2,1), pow(2,2), pow(2,3)
所以4個checkbox 的數值分別為 1,2,4,8
如果使用者提交了 第一個和最後一個checkbox, 儲存的數值是: 1+8=9
使用一個 for 迴圈便可以了
function beforeValidate() {
  foreach ($this->data['User']['question3'] as $k => $v ) {
    $question3 += $v;
  }
}

注意的是應該只有完成了整個mapping 的程序才 返回 true 或 false
要停止儲存, 返回 false
要繼續儲存, 返回 true
取回它們的數值則較為複雜:
$num = 9; //value from DB
$q = 4; //number answers

$question3= array();
for ( $i=1 ; $i<=$q ; $i++ ) {
  if ( $num & pow(2,($i-1)) ) {
    $question3[] = pow(2,($i-1));
  }
}

這個例子示範了 beforeValidate() 和 checkboxes 的組合方法, 但 beforevalidate 其實還有很多很重要的用法
有機會的話再深入研究
@cakephp 1.2.3.8166


No Responses Yet to “CakePHP – formHelper:checkbox & Model:BeforeValidate()”

  1. Leave a Comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s


Follow

Get every new post delivered to your Inbox.