PHP Coding

以下部分引文自《PHP 初級講義》 by 吳弘凱老師 :

http://www.tad0616.net/modules/tad_book3/index.php?op=list_docs&tbsn=19

一、資料結構:

二、索引:

參考 http://zeroplex.blogspot.com/2006/09/mysql.html

MySQL索引分析和優化

轉載 From 松下客 @ 賽迪網

一、什麼是索引?

索 引用來快速地尋找那些具有特定值的記錄,所有MySQL索引都以B-樹的形式保存。如果沒有索引,執行查詢時MySQL必須從第一個記錄開始掃瞄整個表 的所有記錄,直至找到符合要求的記錄。表裡面的記錄數量越多,這個操作的代價就越高。如果作為搜索條件的列上已經創建了索引,MySQL無需掃瞄任何記錄 即可迅速得到目標記錄所在的位置。如果表有1000個記錄,通過索引查找記錄至少要比順序掃瞄記錄快100倍。

對於索引中的每一項,MySQL在內部為它保存一個數據文件中實際

記錄所在位置的「指針」。因此,如果我們要查找name等於「Mike」記錄的 peopleid(SQL命令為「SELECT peopleid FROM people WHERE name='Mike';」),MySQL能夠在name的索引中查找「Mike」值,然後直接轉到數據文件中相應的 行,準確地返回該行的peopleid(999)。在這個過程中,MySQL只需處理一個行就可以返回結果。如果沒有「name」列的索引,MySQL要 掃瞄數據文件中的所有記錄,即1000個記錄!顯然,需要MySQL處理的記錄數量越少,則它完成任務的速度就越快。

二、索引的類型

MySQL提供多種索引類型供選擇:

普通索引

這是最基本的索引類型,而且它沒有唯一性之類的限制。普通索引可以通過以下幾種方式創建:

創建索引,例如CREATE INDEX <索引的名字> ON tablename (列的列表);

修改表,例如ALTER TABLE tablename ADD INDEX [索引的名字] (列的列表);

創建表的時候指定索引,例如CREATE TABLE tablename ( [...], INDEX [索引的名字] (列的列表) );

唯一性索引

這種索引和前面的「普通索引」基本相同,但有一個區別:索引列的所有值都只能出現一次,即必須唯一。唯一性索引可以用以下幾種方式創建:

創建索引,例如CREATE UNIQUE INDEX <索引的名字> ON tablename (列的列表);

修改表,例如ALTER TABLE tablename ADD UNIQUE [索引的名字] (列的列表);

創建表的時候指定索引,例如CREATE TABLE tablename ( [...], UNIQUE [索引的名字] (列的列表) );

主鍵

主鍵是一種唯一性索引,但它必須指定為「PRIMARY KEY」。如果你曾經用過AUTO_INCREMENT類型的列,你可能已經熟悉主鍵之類的概念了。主鍵一般在創建表的時候指定, 例如「CREATE TABLE tablename ( [...], PRIMARY KEY (列的列表) ); 」。但是,我們也可以通過修改表的方式加入主鍵,例如「ALTER TABLE tablename ADD PRIMARY KEY (列的列表); 」。每個表只能有一個主鍵。

全文索引

MySQL從3.23.23版開始支持全文索引和全文檢索。在MySQL中,全文索引的索引類型為FULLTEXT。 全文索引可以在VARCHAR或者 TEXT類型的列上創建。它可以通過CREATE TABLE命令創建,也可以通過ALTER TABLE或CREATE INDEX命令創建。對於大規模的數據集,通過ALTER TABLE(或者CREATE INDEX)命令創建全文索引要比把記錄插入帶有全文索引的空表更快。本文下面的討論不再涉及全文索引,要瞭解更多信息,請參見MySQL documentation。

三、單列索引與多列索引

索引可以是單列索引,也可以是多列索引。

四、最左前綴

多列索引還有另外一個優點,它通過稱為最左前綴(Leftmost Prefixing)的概念體現出來。

五、選擇索引列

在性能優化過程中,選擇在哪些列上創建索引是最重要的步驟之一。

六、分析索引效率

現在我們已經知道了一些如何選擇索引列的知識,但還無法判斷哪一個最有效。MySQL提供了一個內建的SQL命令幫助我們完成這個任務,這就是EXPLAIN命令。EXPLAIN命令的一般語法是:EXPLAIN 。

「對於每一種與另一個表中記錄的組合,MySQL將從當前的表讀取所有帶有匹配索引值的記錄。如果連接操作只使用鍵的最左前綴,或者如果鍵不是 UNIQUE或PRIMARY KEY類型(換句話說,如果連接操作不能根據鍵值選擇出唯一行),則MySQL使用ref連接類型。如果連接操作所用的鍵只匹配少量的記錄,則ref是一 種好的連接類型。」

如果EXPLAIN顯示連接類型是「ALL」,而且你並不想從表裡面選擇出大多數記錄,那麼MySQL的操作效率將非常低,因為它要掃瞄整個表。你可以加入更多的索引來解決這個問題。預知更多信息,請參見MySQL的手冊說明。

possible_keys:

可能可以利用的索引的名字。這裡的索引名字是創建索引時指定的索引暱稱;如果索引沒有暱稱,則默認顯示的是索引中第一個列的名字(在本例中,它是「firstname」)。默認索引名字的含義往往不是很明顯。

Key:

它顯示了MySQL實際使用的索引的名字。如果它為空(或NULL),則MySQL不使用索引。

key_len:

索引中被使用部分的長度,以字節計。在本例中,key_len是102,其中firstname占50字節,lastname占50字節,age占2字節。如果MySQL只使用索引中的firstname部分,則key_len將是50。

ref:

它顯示的是列的名字(或單詞「const」),MySQL將根據這些列來選擇行。在本例中,MySQL根據三個常量選擇行。

rows:

MySQL所認為的它在找到正確的結果之前必須掃瞄的記錄數。顯然,這裡最理想的數字就是1。

Extra:

這裡可能出現不同的選項,其中大多數將對查詢產生負面影響。在本例中,MySQL只是提醒我們它將用WHERE子句限制搜索結果集。

七、索引的缺點

到目前為止,我們討論的都是索引的優點。事實上,索引也是有缺點的。

首先,索引要佔用磁盤空間。通常情況下,這個問題不是很突出。但是,如果你創建每一種可能列組合的索引,索引文件體積的增長速度將遠遠超過數據文件。如果你有一個很大的表,索引文件的大小可能達到操作系統允許的文件限制。

第二,對於需要寫入數據的操作,比如DELETE、UPDATE以及INSERT操作,索引會降低它們的速度。這是因為MySQL不僅要把改動數據寫入數據文件,而且它還要把這些改動寫入索引文件。

【結語】在大型數據庫中,索引是提高速度的一個關鍵因素。不管表的結構是多麼簡單,一次500000行的表掃瞄操作無論如何不會快。如果你的網站上也有這 種大規模的表,那麼你確實應該花些時間去分析可以採用哪些索引,並考慮是否可以改寫查詢以優化應用。要瞭解更多信息,請參見MySQL manual。另外注意,本文假定你所使用的MySQL是3.23版,部分查詢不能在3.22版MySQL上執行。

三、資料庫連線:

$link = @mysql_connect("localhost","database_name","your_password");

  if(empty($link)) die("資料庫無法連線");

  mysql_query("SET NAMES 'utf8'"); //指定資料庫字元格式為 utf8

  mysql_select_db("database_name");

四、讀出資料庫:

SELECT 查詢內容 [FROM `資料表名稱` 篩選條件]

//[ ]內的內容可省略。

//篩選條件= [where 條件式] 或 [group by 欄位名] 或 [having group 的篩選條件] 或 [order by {unsigned_integer | 欄位名 | formula} [asc | desc],...] 或 [limit [起點,]筆數]

//以上篩選條件只能 where, group by, order by, limit 這樣的順序排列。

五、定義變數:

$op = isset($_GET['op'])?$_GET['op']:"";

//以上為三元運算符

//三元運算符: 

//(expr1) ? (expr2) : (expr3);

//如果 expr1 的值為 TRUE,則此運算式的值為 expr2,如果 expr1 的值為 FALSE,則此運算式的值為 expr3

六、改變字元輸出(成網頁)的方式 (可初步防駭或搞亂):

$news['title'] = htmlspecialchars($news['title']);

七、完成 sql 指令後轉至另一頁面(或留在同一頁面):

mysql_query($sql) or die (mysql_error());

header("location:index.php"); //index.php 為完成轉向之頁面。

八、刪除或更新資料,記得加 where 限制範圍,否則是全部資料庫都更改。

九、防駭 sql injection 語法:

//偵測魔術引號設定,替字串的特殊符號自動加上斜線

  if(!get_magic_quotes_gpc()){

    foreach($_POST as $key=>$value){

      $_POST[$key]=addslashes($value);

    }

  }

十、共同設定:

設定一次原始碼,存成一個檔案 (config.php),其餘頁面可共同取用此檔。

示例:

define("_DB_NAME","tad");

//以上為設定常數 _DB_NAME,且為不可修改之值。

include_once "config.php";

//適合條件判斷狀況。

require_once "config.php";

//適合全域設定。

//凡是共同設定檔 (如: config.php ),請確認檔開頭及結尾 (<?php 和 ?>) 不可以有空白字或換行 (enter)。

十一、共同功能:

設定一次原始碼,存成一個檔案 (config.php),其餘頁面可共同取用此檔。

function function_name()

十二、統一流程:

設定文章段落,基本上每頁都可以分為這四個段落,有些 php 頁面可以某些段落設為空白(若不需要的話):

十三、變數過濾 (可防駭):

$news_sn=isset($_REQUEST['news_sn'])?intval($_REQUEST['news_sn']):"";

//把使用者(駭客?)輸入的資料 news_sn 欄位作過濾, $_REQUEST 兼有 $_POST 與 $_GET 的作用。

//intval 是把無關整數的字元統統拿掉。

//所以 $news_sn 被整理為「整數」,然後存放至 $news_sn 變數中。

十四、小強佈景:

include_once('tbs_class.php');

//取出tbs物件

$TBS =new clsTinyButStrong ;

//轉為變數

$TBS->LoadTemplate('theme.html',False) ;

//呼叫模板功能

$TBS->Show() ;

//呼叫秀出功能

十五、變數不能進到 function 中, 只有「常數」可以進到 function 中:

除非使用 global $變數a, $變數b;

十六、表格文字斷行及輸入表單爆框的解法:

十七、分頁物件:

引用 link)

1.引入該物件(在程式開頭第一段)

require_once "pagebar.php";

2.將以下語法,插入到 $sql 與 mysql_query() 之間。

    //PageBar(資料數, 每頁顯示幾筆資料, 最多顯示幾個頁數選項);

    mysql_query($sql);

    $total=mysql_affected_rows();

    $navbar = new PageBar($total, 20, 10);

     //($total, 20, 10)後的兩個數字意思是秀出20筆資料,頁號秀10頁號碼。我的習慣是改為 5, 1。切記第二個數字不可以是 0 , 否則會出現錯誤訊息。

    $mybar = $navbar->makeBar();

    $bar= "<p align='center'>{$mybar['left']}{$mybar['center']}{$mybar['right']}</p>";

    $sql.=$mybar['sql'];

3.「$bar」即分頁工具,將之擺至適當位置即可(如 $main 變數的最後面)。

十八、所見即所得編輯器 CKEditor 用法 (引用、修改自: http://www.tad0616.net/modules/tad_book3/page.php?tbdsn=499) 放在 form.php 中:

方法一:

<script type='text/javascript' src='ckeditor/ckeditor.js'></script>

//(script 語法需放在 $main ,也就是「第三段」的開頭)

//再把 content 欄位(textarea標籤)上,加入「class='ckeditor'」。

<textarea name='content'  class='ckeditor'>

方法二:

<script type='text/javascript' src='ckeditor/ckeditor.js'></script>

//(script 語法需放在 $main ,也就是「第三段」的開頭)

//再把 content 欄位(textarea標籤)上,加入「id='editor'」。

<textarea name='content' cols=30 rows=5 id='editor'>請輸入內容</textarea>

//並在 </textarea> 後加入以下原始碼:

<script type='text/javascript'>

  CKEDITOR.replace('editor' , { skin : 'v2' } );

</script>

自定工具:

以下這段修改(加入 , toolbar : 'Basic' )成--

<script type='text/javascript'>

  CKEDITOR.replace('editor' , { skin : 'v2' , toolbar : 'Basic' );

</script>

//, toolbar : 'Basic' 修改為 , toolbar : 'Full' 就是秀出所有按鈕。修改為 ,toolbar: '自行定義名稱' 需搭配 config.js 的修改才行。

ckeditor 自行定義按鈕的說明連結在此,把網站上提供的原始碼寫入 config.js 上,就可以自行定義。

十九、elfinder 為上傳圖檔工具,可整合至 ckeditor:

(連結)

二十、加入選擇日期的語法:

(引用自此

(1) 語系:lang:'zh-tw'

(2) 佈景:skin:'whyGreen'

(3) 民國年:dateFmt:'民國yyy年MM月dd日'

(4) 含時間:dateFmt:'yyyy-MM-dd HH:mm:ss'

(5) 起始日期:startDate:'1980-05-01' 或 startDate:'%y-%M-%d %H:%m:%s'

(6) 星期一維第一天:firstDayOfWeek:1

(7) 最小日期:minDate:'2006-09-10' 或 minDate:'%y-%M-{%d+2} %H:%m:%s'

(8) 最大日期:maxDate:'2008-12-20'

(8) 週休禁止:disabledDays:[0,6]

二十一、formValidator2.2: