2014年12月19日 星期五

用 jQuery EasyUI 打造輕量級 CMS (四)

昨天搞定系統登入與安裝對話框後, 接下來要真的來處理 install.php 與 login.php 這兩個後端程式. 其實要移植系統只要專心兩三個禮拜應該就可以完成了, 從最早玩 PHP, AutoIT, 到 Javascript 與 Java 都是如此 (Python 還沒寫), 我都針對各語言寫一套常用函式庫來加速開發腳步. 但這回我要詳細記錄過程, 以免久了又淡忘了.

前三篇文章參考 :

用 jQuery EasyUI 打造輕量級 CMS (一)
用 jQuery EasyUI 打造輕量級 CMS (二)
用 jQuery EasyUI 打造輕量級 CMS (三)

在撰寫 install.php 之前, 必須擴充 mysql.php 函式庫, 因為系統安裝程式最主要的工作是新增系統資料表以及填入初始值. 首先要撰寫 create_database() 函式, 用來新增一個資料庫.

function create_database($database, $address=MYSQL_ADDRESS,
                         $username=MYSQL_USERNAME, $password=MYSQL_PASSWORD) {
  $conn=get_connection($address,$username,$password); //取得 MySQL 資料庫連線
  if (!$conn) {return FALSE;} //無法取得連線傳回 FALSE
  $SQL="CREATE DATABASE IF NOT EXISTS ".$database." DEFAULT CHARSET=utf8 ".
       "DEFAULT COLLATE=utf8_unicode_ci";
  $result=mysql_query($SQL, $conn); //成功傳回資源識別字, 失敗傳回 FALSE
  if (mysql_error($conn)) { //若失敗取得資料庫伺服器錯誤敘述
      if (SHOW_ERROR) {
          echo "MySQL CREATE DATABASE Error : ".mysql_error($conn)."<br>";
          }
     }
  return $result;
  }

此函式有四個參數, 後面三個為 MySQL 設定參數, 有預設值, 因此實務上只要傳入資料庫名稱這個參數. 此函式主要使用 CREATE DATABASE 指令來建立資料庫, 成功傳回資源識別字, 失敗傳回 FALSE.

範例 :

  $result=create_database("a000b_12345678_easyuicms");

事實上因為我們已經用 phpMyAdmin 建立資料庫 "a000b_12345678_easyuicms" 了, 所以這個函式應該在 install.php 中用不到, 但是寫加掛的應用子系統時會用到. 執行 CREATE TABLE 需要 MySQL 管理員帳號, 通常代管的虛擬主機只給我們使用者帳號, 因此呼叫 create_table() 函式會失敗, 但在本機的 localhost 則可以, 因為我們是用管理員帳號 root 執行.  

再來要定義 create_table() 函式, 用來新增資料表 :

function create_table($table, $field_array, $database=DATABASE) {
  $conn=get_connection(); //取得 MySQL 資料庫連線
  if (!$conn) {return FALSE;} //無法取得連線傳回 FALSE
  $result=mysql_select_db($database, $conn); //開啟資料庫
  if (!$result) {return FALSE;} //選擇資料庫失敗傳回 FALSE
  $fields_str=""; //欄位字串
  for ($i=0; $i<count($field_array); $i++) {
       list($key,$value)=each($field_array);
       $fields_str.="`".$key."` ".$value;
       if ($i!=count($field_array)-1) {$fields_str .= ",";}
       }
  $SQL="CREATE TABLE IF NOT EXISTS `".$table."` (".$fields_str.")";
  //echo $SQL;
  $result=mysql_query($SQL, $conn);
  if (mysql_error($conn)) { //若失敗取得資料庫伺服器錯誤敘述
      if (SHOW_ERROR) {
          echo "MySQL CREATE TABLE Error : ".mysql_error($conn)."<br>";
          }
      }
  return $result;
  }

此函式傳入三個參數, 但資料庫名稱已有預設值, 故實際上只要傳入資料表名稱以及欄位陣列即可. 這個 $field_array 是關聯式陣列, key 為欄位名稱, value 為欄位型態 :

可用型態如下  :
 VARCHAR(20)   : 可變長度字元 255 bytes (文字)
 CHAR(4)       : 固定長度字元 255 bytes (文字)
 TINYTEXT      : 255 Bytes (文字)
 TEXT          : 65535 bytes (文字)
 MEDIUMTEXT    : 16777215 bytes (文字)
 LONGTEXT      : 4294967295 bytes (文字)
 TINYBLOB      : 255 bytes (文字)
 BLOB          : 65535 bytes (文字,分大小寫)
 MEDIUMBLOB    : 16777215 bytes (文字,分大小寫)
 LONGBLOB      : 4294967295 bytes (文字,分大小寫)
 TINYINT(M)    : 1 bytes (最大顯示寬度 M<=255)
 SMALLINT(M)   : 2 bytes (最大顯示寬度 M<=255)
 MEDIUMINT(M)  : 3 bytes (最大顯示寬度 M<=255)
 INT,INTEGER(M): 4 bytes (最大顯示寬度 M<=255)
 BIGINT(M)     : 8 bytes (總位數 M<=65, 小數位數 D<=30&M-2)
 FLOAT(M,D)    : 4 bytes (總位數 M<=65, 小數位數 D<=30&M-2)
 DOUBLE(M,D)   : 8 bytes (總位數 M<=65, 小數位數 D<=30&M-2)
 DECIMAL(M,D)  : ? bytes (總位數 M<=65, 小數位數 D<=30&M-2)
 DATE          : 3 bytes (YY-MM-DD)
 DATETIME      : 8 bytes (YY-MM-DD HH:MM::SS)
 TIMESTAMP     : 4 bytes (1970-01-01 00:00:00)
 TIME          : 3 bytes (HH:MM:SS)
 YEAR(2|4)     : 1 byte (預設 4)
 ENUM          : 1~2 bytes (儲存單選 radio)
 SET           : 1~8 bytes (儲存多選 checkbox)
可用屬性如下  :
 SIGNED,UNSIGNED : 是否有負值 (數值)
 AUTO_INCREMENT  : 自動增量編號 (數值)
 BINARY          : 字元有大小寫之分 (文字)
 NULL,NOT NULL   : 是否允許不填入資料 (全部)
 DEFAULT         : 預設值
 PRIMARY KEY     : 資料表之唯一主鍵

範例 :

  $field_array["id"]="VARCHAR(20)";
  $field_array["name"]="VARCHAR(255)";
  $field_array["login_counts"]="INT(2)";
  $field_array["serial_no"]="INT(4) UNSIGNED ZEROFILL NOT NULL AUTO_INCREMENT".
                            " PRIMARY KEY";
  $result=create_table("users",$field_array);

接著要建立 insert() 函式, 用來將紀錄寫進指定的資料表內 :

function insert($table, $data_array, $database=DATABASE) {
  $conn=get_connection(); //取得 MySQL 資料庫連線
  if (!$conn) {return FALSE;} //無法取得連線傳回 FALSE
  $result=mysql_select_db($database, $conn); //開啟資料庫
  if (!$result) {return FALSE;} //選擇資料庫失敗傳回 FALSE
  foreach ($data_array as $key => $value) { //產生欄位名稱與值陣列
           $tmp_col[] = $key;
           $tmp_dat[] = "'$value'";
          }
  $columns=join(",", $tmp_col); //轉成字串
  $data=join(",", $tmp_dat); //轉成字串
  $SQL="INSERT INTO ".$table."(".$columns.") VALUES(". $data.")";
  $result=mysql_query($SQL, $conn); //成功傳回資源識別字, 失敗傳回 FALSE
  if (mysql_error($conn)) { //若失敗取得資料庫伺服器錯誤敘述
      if (SHOW_ERROR) {
          echo "MySQL INSERT Error : ".mysql_error($conn)."<br>";
          }
     }
  return $result;
  },

此函式實際上是執行 SQL 的 INSERT INTO 指令, 它具有三個參數, 除資料庫名稱有預設值外, 實際傳入兩個 : 資料表名稱 $table 以及資料陣列 $data_array, 這也是一個關聯式陣列, key 為欄位名稱, value 為欄位值, 傳入的陣列於函式中會用迴圈來產生 SQL 指令中要寫入的資料字串.

範例 :

  $data_array["user"]="tony";
  $data_array["age"]=18;
  $result=insert("users", $data_array); //預設資料庫
  $result=insert("users", $data_array, "stocks");  //指定資料庫

另外再寫一個比較 General 的函式 run_sql(), 可執行所有 SQL 指令. 由於 SQL 指令中的 SELECT 指令會傳回紀錄集, 因此必須分成兩部分處理 :

function run_sql($SQL, $database=DATABASE) {
  $conn=get_connection(); //取得 MySQL 資料庫連線
  if (!$conn) {return FALSE;} //無法取得連線傳回 FALSE
  $result=mysql_select_db($database, $conn); //開啟資料庫
  if (!$result) {return FALSE;} //選擇資料庫失敗傳回 FALSE
  $result=mysql_query($SQL, $conn); //執行 SQL 指令
  if (mysql_error($conn)) { //若失敗取得資料庫伺服器錯誤敘述
      if (SHOW_ERROR) {
          echo "MySQL SELECT Error : ".mysql_error($conn)."<br>";
       }
      return $result; //失敗傳回 FALSE
      } //end of if
  else { //判別是否為 SELECT 指令
      if (substr_count($SQL, "SELECT")==1) { //SELECT 指令
         //從紀錄集資源識別字擷取紀錄為紀錄集陣列
         for ($i=0; $i<mysql_numrows($result); $i++) {
              $RS[$i]=mysql_fetch_array($result);
              } //end of for
         //若紀錄集陣列為一列 (單筆記錄), 則回傳單列紀錄 (即第一列索引 0)
         //if (sizeof($RS)==1) {$RS=$RS[0];}    
         return $RS; //傳回紀錄集陣列
         } //end of else
      else {return $result;} //傳回 TRUE
      } //end of else
  }

此函數有兩個參數, 資料庫名稱有預設值, 故只需傳入 SQL 指令字串即可. 如果 SQL 是 SELECT 指令, 還需要判斷傳回的紀錄集是否只有一筆, 若只有一筆就傳回單筆紀錄, 若是多筆就傳回紀錄集陣列.

範例 :

  $result=run_sql("DELETE FROM users WHERE id='peter'"); //注意, DELETE 無 *
  $SQL="UPDATE users SET login_count=5,name='彼得' WHERE id='peter'";
  $SQL="INSERT INTO users(id,name) VALUES('peter','彼得')";
  $result=run_sql($SQL);
  $RS=run_sql("SELECT * FROM tabs ORDER BY tab_order); //多筆紀錄
  for ($i=0; $i<count($RS); $i++) { //走訪紀錄集陣列
       echo $RS[$i]["tab_name"].",".$RS[$i]["age"];
       }

把這四個函式放進 mysql.php 中就可以開始撰寫 install.php 安裝程式了. 系統安裝主要有下列 9 個資料表要建立, 並初始化 :
  1. sys_settings :
    包括 EasyUI 主題布景, 網站標題, 系統狀態, 以及資安有關的密碼型態等. 
  2. sys_tabs :
    首頁與管理等平台相關的頁籤.
  3. sys_nav_blocks :
    管理導覽列. 
  4. sys_nav_links :
    儲存導覽列超連結.
  5. sys_header_links :
    儲存標題列超連結.
  6. sys_themes :
    用來儲存 EasyUI 的主題布景種類. 
  7. sys_users :
    儲存使用者資料.
  8. sys_visitors :
    紀錄到訪者資料.
  9. sys_apps :
    紀錄所掛載的應用子系統. 
# 2014-12-24 修改版 (login/logout/change_theme 整合為 sys.php 前)



沒有留言:

張貼留言