:::

MarkDown

``` - 下拉選單:<select name="名稱" size=1>選項</select> ,如: ```markup ``` - 單選框:<input type="radio" name="名稱" value="值 1">選項文字 1,如: ```markup
``` - 複選框:<input type="checkbox" name="名稱\[\]" value="值 1">選項文字 1,如: ```markup
``` - 隱藏框與送出表單 ```php // 表單函數 function post_form() { global $content,$smarty; // 加入預設值 $content = [ /**略*/ ]; $next_op = 'add'; $smarty->assign('next_op', $next_op); } ``` ```markup
``` ### 二、PHP的變數過濾 1. 外來變數 - 用post方法傳過來的,我們用 $\_POST\['變數名稱'\] 接收。 - 用get方法傳過來的,我們用 $\_GET\['變數名稱'\] 接收。 - 用 $\_REQUEST\['變數名稱'\] 同時可接收來自 post、get 和 cookie 的變數 。 2. 過濾外來變數 - 外來變數通常來自使用者輸入或者比較容易竄改,所以,凡是外面傳來的變數,一律要進行變數過濾。 - 一般讀出文字可用內建的 [htmlspecialchars()](http://php.net/manual/en/function.htmlspecialchars.php) 函數來過濾。 - 直接用 [htmlspecialchars($string)](http://php.net/manual/en/function.htmlspecialchars.php) 的話,預設只轉化雙引號,不對單引號做轉義,所以,這樣用htmlspecialchars($string,ENT\_QUOTES) 更好。 - 亦可利用PHP內建的 [filter\_var() 函數](http://php.net/manual/en/function.filter-var.php)來過濾變數。 - 幾種常用過濾方法,[完整過濾器可由此查看](http://php.net/manual/en/filter.filters.php):
名稱 功用
FILTER\_CALLBACK option可以讓開發者用自訂的function處理
FILTER\_SANITIZE\_STRING 去除標籤或特殊字元(html標籤會直接被消除)
FILTER\_SANITIZE\_ENCODED 與urlencode()相同,過濾特殊字串
FILTER\_SANITIZE\_MAGIC\_QUOTES 過濾針對SQL injection做過濾(例如單、雙引號)
FILTER\_SANITIZE\_SPECIAL\_CHARS 針對HTML做encoding,例如<會轉成&lt;
FILTER\_SANITIZE\_EMAIL 過濾e-mail,刪除e-mail格式不該出現的字元(除了$-\_.+!\*'{}|^~\[\]`#%/?@&=和數字),例如a(b)@gmail.com會被過濾成ab@gmail.com
FILTER\_SANITIZE\_URL 過濾URL,刪除URL格式不該出現的字元
FILTER\_SANITIZE\_NUMBER\_INT 刪除所有字元,只留下數字與+-符號
FILTER\_SANITIZE\_NUMBER\_FLOAT 刪除所有字元,只留下數字和+-.,eE
FILTER\_VALIDATE\_INT 判斷數字是否有在範圍內
FILTER\_VALIDATE\_BOOLEAN 判斷布林值,1、true、on、yes都會判斷成true,反之為false,若是這些以外的值會回傳NULL
FILTER\_VALIDATE\_FLOAT 判斷是否為浮點數
FILTER\_VALIDATE\_REGEXP 利用regexp做驗證
FILTER\_VALIDATE\_URL URL驗證
FILTER\_VALIDATE\_EMAIL e-mail驗證
FILTER\_VALIDATE\_IP IP驗證
- ```php $op= isset($_REQUEST['op']) ? filter_var($_REQUEST['op'], FILTER_SANITIZE_SPECIAL_CHARS) : ""; ``` - `filter_var($string, FILTER_SANITIZE_SPECIAL_CHARS)` 換行麻煩,因此若要輸出HTML的換行文字過濾仍建議採用 `htmlspecialchars($string, ENT_QUOTES);` 對$smarty樣板輸出有較好支援性 `{$content.directions|nl2br}` - 過濾數字: 數字的過濾,只要加個`(int)`即可,如`$sn=(int)$_GET['sn'];` - 不同過濾器的運用時機: - 一般有大量文字夾雜HTML語法用 `htmlspecialchars($string,ENT_QUOTES) `。 - 要在php檔案中運算用的,請用PHP來過濾 `filter_var($string, FILTER_SANITIZE_SPECIAL_CHARS)` - 要寫入資料庫的,用資料庫的`real_escape_string()`來過濾。 ### 三、寫入資料到資料庫 1. 要操作MySQL,必須用SQL語言,新增資料的SQL語法如下(大小寫無關): ```markup INSERT [INTO] `資料表名稱` [(`欄位1`, `欄位2`...)] VALUES ('值1', '值2'...) ``` 2. 建議凡是資料庫名稱、資料表名稱、欄位名稱都用重音符號```包起來。 3. 凡是「值」的,都用單引號`'`包起來。 4. 過濾變數: 利用 $db->real\_escape\_string() 過濾資料,目的是順利讓所有資料存入資料庫,並避免隱碼攻擊。 ```php $title = $db->real_escape_string($_POST['title']); ``` 5. `$db->query($sql)` 就是送執行指令到資料庫。 6. `$db->error` 會秀出資料庫傳回來的錯誤訊息。 7. 取得寫入時該資料產生的流水號:`$db->insert_id` 8. 程式碼: ```php //新增清單 function add() { global $db; //過濾變數 $title = $db->real_escape_string($_POST['title']); $directions = $db->real_escape_string($_POST['directions']); $end = $db->real_escape_string($_POST['end']); $priority = $db->real_escape_string($_POST['priority']); $assign = $db->real_escape_string(implode(';', $_POST['assign'])); $done = intval($_POST['done']); // 連線資料庫 $sql = "INSERT INTO `list` ( `title`, `directions`, `end`, `priority`, `assign`, `done`,`create_time`,`update_time`) VALUES ('{$title}', '{$directions}', '{$end}', '{$priority}', '{$assign}', '{$done}',now(),now())"; if (!$db->query($sql)) { throw new Exception($db->error); } $sn = $db->insert_id; return $sn; } ``` ### 四、寫入後須轉向 1. 凡是寫入、修改、刪除,進行完都應該做轉向,避免使用者重新整理畫面,又重複執行寫入、修改或刪除:`header("location: index.php?sn={$sn}");` 2. `header()`函數基本上是設定文件檔頭,其中 location屬性可以指定文件轉向,故利用它來達成轉向功能。 3. 程式碼:`siwtch` ```php switch ($op) { case 'add': $sn = add(); // 無提示訊息 // header("location: index.php?sn={$sn}"); // exit; // 有提示訊息 echo ";"; exit; ``` ### 五、從資料庫中讀取資料 1. 讀取資料庫的內容,一律用 select 語法: ```markup SELECT `查詢的欄位` [FROM `資料表名稱` 附加的篩選條件] ``` 2. 其中篩選條件語法如下: ```css [where 篩選條件] [group by `欄位名稱`][having group的篩選條件] [order by {unsigned_integer | `欄位名稱` | formula} [asc | desc] ,...] [limit [起點,] 筆數] ``` 3. 有順序關係,需注意。 ### 六、 從資料庫取得資料的方法 1. 寫SQL送去資料庫執行後,會傳回一個資源變數物件,如`$result` 2. 可以利用`$result`的各種取得資料方法,將資料一筆一筆取回。 3. 一筆資料以上的資料,請放至`while(){}`迴圈中取回。 4. 利用 `$result->fetch_assoc() `取出的資料陣列,會以資料表欄位名稱為陣列索引; 以`$result->fetch_row()` 取出的資料陣列,是以欄位順序為陣列索引,通常搭配`list()`使用。 5. 練習`$data=$result->fetch_assoc();` 6. 練習`$data=$result->fetch_row();` 7. 搭配 `list($sn, $title, $directions,$end,$priority,$assign,$done, $create_time, $update_time)=$result->fetch_row();` 效果同 `$data=$result->fetch_assoc();` 8. 完整程式碼: ```perl // 列出所有資料 function list_all() { global $db, $smarty, $content; $sql = "select * from `list` order by end"; $result = $db->query($sql); if (!$result) { throw new Exception($db->error); } $content = []; // 法一 // while ($data = $result->fetch_assoc()) { // $content[] = $data; // } // 法二(樣板要改,不建議) // while ($data = $result->fetch_row()) { // $content[] = $data; // } // 法三 $i = 0; while (list($sn, $title, $directions, $end, $priority, $assign, $done, $create_time, $update_time) = $result->fetch_row()) { $content[$i]['sn'] = $sn; $content[$i]['title'] = $title; $content[$i]['directions'] = $directions; $content[$i]['end'] = $end; $content[$i]['priority'] = $priority; $content[$i]['assign'] = $assign; $content[$i]['done'] = $done; $content[$i]['create_time'] = $create_time; $content[$i]['update_time'] = $update_time; $i++; } } ``` ### 七、幾個常用的迴圈用法 1. 不曉得迴圈數的 ```php while(條件為真){ //執行動作 } ``` 2. 已知道迴圈數 ```php for($i=0;$i<迴圈數;$i++){ //執行動作 } ``` - [遞迴運算元](https://www.php.net/manual/en/language.operators.increment.php)( i++) 3. 抽取陣列 ```php foreach($陣列 as $索引=>$值){ //執行動作 } ``` ### 八、 讀出資料的安全性過濾 1. 利用PHP的 filter\_var 過濾器 `FILTER_SANITIZE_SPECIAL_CHARS`:同`htmlspecialchars()` 來過濾字串。 ```php //過濾變數 $title = filter_var($title, FILTER_SANITIZE_SPECIAL_CHARS); $directions = htmlspecialchars($directions, ENT_QUOTES); $priority = filter_var($priority, FILTER_SANITIZE_SPECIAL_CHARS); ``` 2. 若是所見及所得編輯器,如CKEDITOR不需要過濾。