今天發現 PHP8 裡有支程式執行時會出現以下錯誤訊息:
Fatal error: Uncaught Error: Call to undefined function ImageCreateFromJPEG()
我們要使用處理圖檔 (Image Processing and Generation) 的內建函式庫 GD,但這支程式在 PHP7 時期是會跑得好好的,上網搜尋了一下,找到兩篇文章:
今天發現 PHP8 裡有支程式執行時會出現以下錯誤訊息:
Fatal error: Uncaught Error: Call to undefined function ImageCreateFromJPEG()
我們要使用處理圖檔 (Image Processing and Generation) 的內建函式庫 GD,但這支程式在 PHP7 時期是會跑得好好的,上網搜尋了一下,找到兩篇文章:
使用者反映,有一個頁面上的資料會出現問號,後來我發現問題是該頁面會先載入一份 Big5 文字檔,內容有這樣的文字:
分子/分母
因為頁面最終會把內容全部整理好後以 UTF-8 輸出,這段字串會經由 mb_convert_encoding($string,"utf-8","big5") 處理,全型的斜線就會變成問號:
分子?分母
但以前在 PHP 7 以前沒有人反映過這個頁面有問題,搜尋一下,在 "PHP8.1: mb_convert_encoding not working with ASCII chars above 127" 這篇有人提到,他原始輸入的文字是 "ü",但是會被轉換為 "?"。原本他的 mb_convert_encoding 是將 ANSII 轉為 UTF-8,最後他的解法是 ISO-8859-1 轉為 UTF-8。
在 PHP 裡執行 AES 加解密,比想像中簡單,加密 (encrypt) 只要使用:
<?php
function _encrypt($data, $encryption_key) {
昨天有一個頁面出現錯誤訊息:「An error occurred translating the query string to UTF-16: 在多位元組的目的字碼頁中,沒有這個 Unicode 字元可以對應到的字元。」
確認了內容,是因為 SQL 語法裡有中文,該 PHP 檔案是 ANSI (Big5) 編碼,程式裡沒有指定語系。
在這個情境下,處理方法有兩種:
手邊有一個檔案上傳功能,要從 MySQL 轉到 SQL server,原始的內容是用 PDO 的 bindValue 把二進制的檔案內容塞進資料庫:
但實際寫入會一直出現錯誤訊息:
看起來就是 binary 塞不進去資料庫裡。
原本對 Sybase 查詢的程式,配合資料庫要移轉到 MSSQL (SQL server),要做調整。發現在執行到 fetch 時奇慢無比,在 SQL server management studio 裡可以秒回的查詢,在程式裡要跑 12~15 秒。
execute 回應的速度很快,真正卡住的點是 fetch()。所以用 "PHP pdo fetch slow" 當關鍵字找了一些解法:
剛剛在算一組數字,全都是兩位小數的加法,原本預期是:
6676.18 + 339.37 + 3667.65 + 1204.70 + 4286.02 = 16173.92
但實際計算結果卻令人震驚!
6676.18 + 339.37 + 3667.65 + 1204.70 + 4286.02 = 16173.920000000002
後面的 "0000000002" 哪來的啦!
今天 user 來電,跟我說我的程式沒有正常送出月報。執行後我如果嘗試印出 PHPmailer 的 errorInfo,會出現以下錯誤訊息:
SMTP connect() failed. https://github.com/PHPMailer/PHPMailer/wiki/Troubleshooting
只說 SMTP 連不上,超簡約的錯誤訊息。請 IT 幫忙查 mail server,看到以下訊息:
connect_from=[xxx.xxx.xxx.xxx],state=550 X.7 Couldn't start TLS!
有支 PHP 程式在 Windows 主機上跑得好好的,但在 Linux 會出現問題。
程式出錯的地方是用 PHP PDO 連線到 Sybase,資料會無法取回。把 PDOStatement 的 errorInfo() 印出來,看到錯誤訊息是不允許將 VARCHAR 轉型為 NUMERIC。
Array (
因為要防止 SQL injection,需要做參數化查詢。以往都是把參數 (SQL params) 先放在 array,再把 SQL 與 array 記錄到 log 裡,不過總覺得這做法不太直覺,每次要 debug 也要自己在那邊兜來兜去。
上網查一下發現有 PDOStatement::debugDumpParams 這個函式可以用,可以印出原始的 SQL(未代入參數)、代入參數後的 SQL、各參數,不過這個 function 是無回傳值的 (void),會直接印出到畫面上。
查了一下有一篇 "Something like debugDumpParams in pdo settable to a string",利用緩衝區先把 debugDumpParams() 的內容接住:
要在 PHP 產出 Word 檔,因為之前用同事導入的 PHPExcel 的體驗還不錯,所以決定這次要用 PHPWord。但是事情沒有我想像的簡單,到 PHPWord 的 Github 專案下載專案檔案後,直接解壓縮 src 目錄放到、專案目錄下,光是要按照 PHPWord 的說明文件產生最基本的檔案,就出現錯誤訊息:
PHP Fatal error: Uncaught Exception: Could not find file '/autoload.php'. It is generated by Composer. Use 'install --prefer-source' or 'update --prefer-source' Composer commands to move forward
回頭從安裝仔細看 PHPWord 的說明裡的安裝步驟,發現要用 copmopser 安裝,才會產生前述的 "Autoloader.php" 檔案。
我們是使用 PHP 開發、以 CheckMarx 進行源碼檢測。在這篇持續補充各種 CheckMarx 修補心得~
弱點:
程式完成後要進 CheckMarx 掃描,確認原始碼沒有弱點。但是 CheckMarx 非常敏感,看到以下系統變數,就會判斷可能成為注入點:
有支有陣子沒怎麼用到的程式忽然無法完整跑完,一開始看到 Apache 上的錯誤訊息寫這樣:
[Tue Jun 02 12:35:38.163897 2020] [proxy_fcgi:error] [pid 000000:tid 999912345678900] (70007)The timeout specified has expired: [client 127.0.0.1:12345] AH01075: Error dispatching request to : (polling)
大部分的文章說是需要把逾時的時間拉大一點,讓程式有機會可以慢慢跑完,譬如去修改 Apache 的 config 裡的以下值:
同事反映他用 PHP Mailer 6.0.3 寄信時,寄件人的名字無法正常顯示中文,就算在 $mail->setForm() 的第二個寄件者參數,做了 mb_convert_encoding 也一樣。
看了一下是他沒有設定到語系設定,可參考 "PHPMailer character encoding issues" 這篇:
$mail->CharSet = 'UTF-8';
加完就沒事了,打完收工。
手上有幾個舊的網站用 TemplatePower 作為樣版,早期相安無事,現在 PHP 升到 PHP 7 以後,就看到系統會不停的噴出類似這樣的 error log:
PHP Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; TemplatePower has a deprecated constructor in D:\templatepower\class.TemplatePower.inc.php on line 499
雖然頁面還是可以照樣正常套版,但是在 debug 時一直看到這些 log 交錯其中,覺得神煩,參考了 stackoverflow "PHP7 Constructor class name",原來以前舊版的 PHP 的物件導向中,類別 (class) 的建構方法 (constructor) 可以同名,現在必須要統一使用建構子 (__construct)。
所以依照 PHP 的新規則稍作修改,主要是加個 function __construct() { } 來做本來物件初始化時要做的事,像是從這樣(大約在第 60 行):
同事希望我判斷她下的查詢條件是否是整整一個月,我本來以為用 date_diff 就可以算出來,但在兩台不同電腦上跑出不一樣的結果來。比較了兩台機器的差異,主要是時區 (Timezone) 不相同。
寫一小段程式來測試一下:
<?php
最近有一個頁面,要把檔案上傳到 server 上之後,把檔案本身直接轉成 BLOB 後塞到資料庫裡,資料欄位我開成 mediumblob。
`testfile` mediumblob comment '使用者上傳檔案',
小檔案上傳還沒問題,但大檔案上傳遇到一些狀況。首先是 Apache 會吐 HTTP 500 (Internal Server Error)。
我想了一下,在 Apache 的 httpd.conf 把 FastCGI 的 MaxRequestLen 調大一點(我調到 35MB):
很少寫 PHP script,這次要拆解小有份量的 Apache 記錄檔 (log),來練習一下。
用讀檔的模式來一行一行載入 log 檔後,用正規表示式來拆開 LOG,把它塞進資料庫裡,以便可以再運用。
首先,開一個資料表來放 log。