2019年11月2日 星期六

EasyUICMS (PHP 版) mysqli 函式庫更新備忘

因為昨晚在樹莓派安裝 PHP 出現問題, 所以乾脆在 Win10 筆電上用 xampp 免安裝版來把 EasyUICMS 重新架起來, 參考 :

安裝 XAMPP PHP 架站工具包

但安裝 EasyUICMS 時卻發現安裝成功的無回應, 不過用 phpMyAdmin 檢查資料庫又都正常建立, 直接瀏覽首頁有出現登入畫面, 只是輸入預設帳密同樣沒回應 :




開啟 Chrome F12 偵錯模式發現, 原來是 mysqli 函式庫裡面我用了 each() 函數來解析關聯式陣列的 key 與 value, 而此函數已經被廢棄不用了 (deprecated), 訊息如下 :




<b>Deprecated</b>:  The each() function is deprecated. This message will be suppressed on further calls in <b>D:\xampp\htdocs\twstock\lib\mysqli.php</b> on line <b>232</b><br />
{"status":"success","msg":""}

意思是 /lib/mysqli.php 函式庫第 232 行的 each() 函數被廢止, 導致 JSON 回應訊息的 msg 屬性為空字串, 所以登入畫面無回應. 程式流程如下 :

index.php --> sys.php --> /lib/mysqli.php

查了一下 sys.php 相關程式碼, 是在 login 這個操作時呼叫了 mysqli,php 函式庫中的 update() 函數去更新使用者登入失敗次數所導致 :

switch ($op) {
  case "login" : {
     .......
            //處理嚴格認證政策 : 失敗次數歸零
            if ($auth_policy=="strict") { //嚴格認證
              //重設 users 中的 login_fail_count
              $data_array["login_fail_count"]=0;
              $ret=update("sys_users",$data_array,"account",$account);
              $data_array=null;
              } //end of if
     .......
     }
  }

而在 lib/myqli.php 裡, update() 函數使用了 each() 來解開關聯式陣列中的 key 與 value 來製作 SQL 的 UPDATE 指令 :

  for ($i=0; $i<$cnt; $i++) {
       list($key,$value)=each($data_array);
       $setting_list.= $key."="."\"".$value."\"";
       if ($i!=count($data_array)-1) {$setting_list .= ",";}
       }

查詢 PHP 文件發現 each() 已在 PHP 7.2.0 之後被廢棄不用了, 參考 :

https://www.php.net/manual/en/function.each.php

"Warning This function has been DEPRECATED as of PHP 7.2.0. Relying on this function is highly discouraged."

而我使用的 XAMPP 的 PHP 版本剛好是 7.2.0 之後的 7.2.4 版 :

"Welcome to XAMPP for Windows 7.2.4"

實在懶得去找舊版 XAMPP 來跑, 不如趁此機會將 mysqli 函式庫升版. 替代 each() 的方法很簡單, 就是改用 foreach 迴圈即可, 參考 :

How to resolve this deprecated function each php

在 mysqli.php 函式庫中用到 each() 的函數不只 update(), 只要含有 list($key,$value)=each($data_array) 的程式碼都改寫, 例如 :

  .......
  $cnt=count($data_array);
  for ($i=0; $i<$cnt; $i++) {
       list($key,$value)=each($data_array);
       $fields_str.="`".$key."` ".$value;
       if ($i!=count($data_array)-1) {$fields_str .= ",";}
       }
  $SQL="CREATE TABLE IF NOT EXISTS `".$table."` (".$fields_str.")";
  .......

更新為如下寫法 :

  .......
  $i=0;
  foreach ($data_array as $key => $value) {
       $fields_str.="`".$key."` ".$value;
       if ($i != count($data_array)-1) {$fields_str .= ",";}
       ++$i;
       }
  ......

注意, mysqli.php 函式庫中的 create_table() 與 create_fields() 這兩個函數原先用的參數名為 $field_array, 這次全都一致改為 $data_array. 經過如此調整後重新瀏覽首頁就可正常安裝系統了 :





沒想到 PHP 升版造成的麻煩還真不少. 雖然 PHP 較少用, 但學過的功夫忘掉卻也可惜, 忙完這陣子後要整理一下 PHP 筆記了, 畢竟目前免費主機還是以 PHP 主機最多.

另外值得一記的是, 我把 index.php 與 main.php裡面的所有 jQuery 相關套件都改為本地提供, 不再使用 CDN, 原因是在檢視 Hostinger 上的網站時, 發現 EasyUI 的版面格式跑掉了, 改成本地供檔就沒問題了 (EasyUI v1.4.1, 還好當時有下載保存).

我想應該是新版 EasyUI 有 bug, 前陣子在測試 Django 模板時也發現 Tab 面版出現標頭與內容不匹配情形 (內容部份凸出來), 等再回頭測試 Django 時也要改為本地供檔, CDN 供檔無法保證網頁外觀品質.

2019-11-02 補充  :

晚上回到鄉下將專案上傳到 000webhost 測試, 安裝正常但無法登入, 檢查 sys_users 資料表竟然無預設之管理員密碼, 即 install.php 中的 insert 指令執行失敗, 檢查研判是定義欄位時, 有些欄位我多加了 NOT NULL, 而 insert 時又沒有填寫這些 NOT NULL 欄位的話, 在 localhost 本機沒問題, 但在某些主機可能會有問題.

    //建立 sys_users 資料表
    $data_array["id"]="smallint(6) NOT NULL AUTO_INCREMENT PRIMARY KEY";
    $data_array["account"]="varchar(255)";
    $data_array["password"]="varchar(255)";
    $data_array["name"]="varchar(255)";
    $data_array["theme"]="varchar(255)";
    $data_array["email"]="varchar(255)";
    $data_array["maillist"]="char(1)"; //"Y","N"
    $data_array["level"]="tinyint(4)"; //0(unapproved),1(users), ~9(admin)
    $data_array["mobile_phone"]="varchar(255)"; //for SMS
    $data_array["send_sms"]="char(1)"; //"Y","N", 是否傳送簡訊
    $data_array["login_count"]="int(11) NOT NULL DEFAULT '0'"; //登入成功次數
    $data_array["last_login"]="datetime NOT NULL"; //最近一次登入時間
    $data_array["login_fail_count"]="tinyint(4) NOT NULL DEFAULT 0"; //失敗次數
    $data_array["last_3_passwords"]="varchar(255)"; //最近三次密碼a-b-c
    $data_array["locked"]="char(1) NOT NULL DEFAULT 'N'"; //'Y'=locked
    $result=create_table("sys_users",$data_array);
    if ($result) {$msg .= "建立資料表 sys_users ... 完成!
";}

去除這些多餘的 NOT NULL 後狀況解除.

沒有留言 :