Troubleshooting of PHP errors
PHP 問題的排除與解決
檔案操作有關
可否讀取或寫入:例如 imagejpeg($canvas, $filename, 100); 沒有顯示錯誤訊息,則需要
- 檢查檔案或目錄是否存在 file_exists
- 如果是上傳檔案,需要檢查暫存目錄是否可以寫入 upload - PHP way to find the web server's temp path? - Stack Overflow
- 檢查該檔案所在該目錄是否已經建立,若未建立則需要建立 mkdir,並設定可以寫入。如果產生位置是在多層子目錄下 (巢狀的多層目錄),則需要啟用 $recursive [1]
- 檢查該檔案是否可以寫入 is_writable: 如果要刪除檔案,需要檢查是否可以寫入
PHP 技術問題處理
不知道載入哪一個 php.ini 設定檔
使用 console command,輸入命令 php --ini
> php --ini Configuration File (php.ini) Path: C:\Windows Loaded Configuration File: C:\xampp\php\php.ini Scan for additional .ini files in: (none) Additional .ini files parsed: (none)
也可使用 phpinfo 確認「Loaded Configuration File」
- command on Linux / macOS
: echo "<?php phpinfo(); ?>" | php | grep "Loaded Configuration File" - 或指定完整 php 路徑 command: echo "<?php phpinfo(); ?>" | /Applications/XAMPP/bin/php | grep "Loaded Configuration File"
執行PHP時顯示原始碼的錯誤
- 確認伺服器是否能執行 PHP。驗證方式: phpinfo/ phpinfo from the command line | commandlinefu.com
- 如果 PHP 使用 short tag語法撰寫,但是沒有啟用 short_open_tag ,會造成顯示原始碼的錯誤。解法: php.ini 檔案 需要開啟 short_open_tag = Off -> On
錯誤訊息: ERROR: 00000::
- 原因: 想要刪除的資料不在 MySQL 資料庫內,進行刪除時,會發生的錯誤。
- 解決方法: 先檢查該資料是否存在,再進行刪除。
錯誤訊息: phpinfo() has been disabled
PHP Warning: phpinfo() has been disabled for security reasons in /path/to/phpinfo.php on line xx
- 原因: 網管關閉使用 phpinfo
替代解決方法: 使用 console command
- php -i | grep -i "變數名稱" 或 /path/to/bin/php -i | grep -i "變數名稱" for Linux
- php -i 變數 --info 、 -i 或 -ini,用途顯示PHP資訊或設定值。(PHP information and configuration 摘錄自man php)
- | 管線命令 (pipe),詳 鳥哥的 Linux 私房菜 -- 學習 bash shell
- grep -i 變數 -i 代表忽略搜尋關鍵字或搜尋條件 (pattern) 的大小寫
- /path/to/bin/php -m 列出載入的模組[2]
錯誤訊息: PHP syntax error “unexpected $end”
解決方法
- 檢查括弧是否封閉: 使用 Notepad++ctrl + b 檢查括弧是否封閉 或 使用 Sublime Textctrl + m 檢查括弧是否封閉
- <?php 是否簡寫為 shorttag <?
錯誤訊息: SMTP Error: Could not connect to SMTP host.
錯誤訊息: Invalid address: SMTP -> ERROR: Failed to connect to server: Permission denied (13) SMTP Error: Could not connect to SMTP host. Mailer Error: SMTP Error: Could not connect to SMTP host.
解決方法
- 檢查 PHP 模組是否安裝 OpenSSL php -r "phpinfo();" | grep -i "OpenSSL support" 或 php -i | grep -i OpenSSL for Linux
預期結果:
OpenSSL support => enabled
- 是否可以連線到 SMTP 主機nslookup smtp.gmail.com 或 telnet smtp.gmail.com port (例子中以 gmail 作為 smtp 伺服器)
telnet smtp.gmail.com 465 預期結果:
Trying 74.125.129.109... Connected to smtp.gmail.com. Escape character is '^]'. ^] //註:(Windows) 輸入 ctrl + ] 兩個按鍵,(Mac) 輸入 control + ] 兩個按鍵 telnet> quit Connection closed.
非預期結果:請調整防火牆設定
Trying x.x.x.x... telnet: connect to address x.x.x.x: Connection refused
預期結果:
# getsebool httpd_can_sendmail httpd_can_sendmail --> on # getsebool httpd_can_network_connect httpd_can_network_connect --> on
非預期結果:
# getsebool httpd_can_sendmail httpd_can_sendmail --> off # getsebool httpd_can_network_connect httpd_can_network_connect --> off
需要輸入指令:
# setsebool -P httpd_can_sendmail 1 # setsebool -P httpd_can_network_connect 1
錯誤訊息: Allowed memory size of XXX bytes exhausted (out of memory)
- 訊息: PHP Fatal error: Allowed memory size of XXX bytes exhausted (tried to allocate XX bytes)
- 原因: 一次讀取13萬行的資料,發生錯誤
- 解決方法:
- 減少每次讀取的資料行數,例如每次只讀取 50 行的資料筆數來做處理。
- foreach 時,與其寫入整個陣列到記憶體,可以改用 Generators 寫法,節省記憶體的使用。詳見: PHP: Generators overview - Manual
錯誤訊息: It is not safe to rely on the system's timezone settings
- 訊息: Warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone.
- 原因: 沒有設定時區
- 解決方法: 使用 date() 或 strtotime() 等時間相關函數之前,先設定時區,例 date_default_timezone_set("Asia/Taipei")
移除非預期的空白(全形空白)
需要額外移除 'IDEOGRAPHIC SPACE' (U+3000) 全形空白
$string = str_replace(json_decode('"\u3000"'), "", $string);
$string = trim($string);
PHPExcel 產生的 Excel 檔案,開啟後看到一堆亂碼
狀況1: 開啟 Excel 檔案,看到最前面有 NOTICE 的錯誤訊息,例如 <b>Notice</b>: Constant CONST_XXX already defined in <b>path\to\script.php</b> on line xx
- 解法: 關閉錯誤訊息輸出 ex: error_reporting(0); 以及修正 NOTICE 訊息指涉的問題,例如例子中常數重複宣告的問題。
狀況2: 開啟 Excel 檔案,看到最前面有 Fatal error 之類的錯誤訊息
- 解法: 關閉錯誤訊息輸出 ex: error_reporting(0); ,以及修正 Fatal error 訊息指涉的問題。
狀況3: 開啟 Excel 檔案,看到有儲存格位址之類的錯誤訊息
- 解法: 該儲存格內容以等號 (=) 開始,卻不是函數。解決方式是將儲存格內容的最前面加一個單引號 (') 或者是加個空白。
composer.phar: command not found
錯誤訊息: 透過 composer 安裝 PHP 套件時,例如 composer require league/csv,出現錯誤訊息「composer.phar: command not found」
- 解法: composer.phar 需要 PHP 執行,由於系統沒有設定 PHP 的路徑,因此需要說明 PHP 的完整路徑,例如/path/to/php /path/to/composer require league/csv
Could not open input file: composer.phar
錯誤訊息: 透過 composer 安裝 PHP 套件時,例如 composer require league/csv,出現錯誤訊息「Could not open input file: composer.phar」
- 解法: 如果沒有設定 composer.phar 的 PATH ,需要清楚告知 composer.phar 的完整檔案路徑,例如/path/to/php /path/to/composer require league/csv
使用者操作/使用者輸入的內容
避免的 coding 習慣
- 避免使用簡化的的變數名稱,例如 $sd 也許一開始還會記得,但是過一陣子就會忘記這是什麼
- 重複複製貼上的內容,但是內容可能常被使用者更改,導致內容更新困難,需要修改多處的程式碼
- 將測試網址 (127.0.0.1 或 localhost) 寫死在程式碼內,導致日後移機或對外公開網站服務時,需要修改多處的程式碼
unified coding style
variable: $var
tools
tester
- $ PHP Code Tester for macOS
documentation
- Dash 3 for macOS
- API Docs & Snippets. Integrates with Xcode, Alfred, TextWrangler and many more. on the Mac App Store - DevDocs API Documentation
troubleshooting steps of function
simply the question
- Is the function_exists?
- Extension dependency? Install the extension you need.
- If not, looking for the alternative functions.
- Was the function really executed? Maybe using the __LINE__ to examin the logic.
- Disable the logical judgement and just print text using var_dump or print_r functions.
- Check the if-else condition was satisfied or not cf: Java: String Comparison It's logical (compiler will not show the warning) but wrong.
logging
native error logging
- PHP log: check the configuration file: /etc/php.ini (the location of configuration file can be verified by phpinfo() )
(for production site) unmark theese lines in the php.ini and restart Apache service
log_errors = On error_log = "php_error.log"
(for development site) using error_reporting
error_reporting(E_ALL);
$log = print_r($variable, true); //save to the log file $log = print_r(debug_backtrace(), true); //Generates a backtrace and save to the log file
capture the result of var_dump: ob_start
- php - How can I capture the result of var_dump to a string? - Stack Overflow
- PHP: error_log - Manual
ob_start(); var_dump($some_variable); $result = ob_get_clean(); error_log($result, 3, 'd:/result.log');
QuickForm
$result = var_dump($some_variable);
$form->addElement('html', $result);
CodeIgniter: php - How to configure Codeigniter to report all errors? - Stack Overflow
show the line number and filename
echo 'Houston, we've had a problem '. __line__ . ' ' . __FILE__ ."<br />";
more on PHP: Magic constants, monolog
references
- ↑ php - Create a folder if it doesn't already exist - Stack Overflow code snippet: mkdir('path/to/directory', 0755, true);
- ↑ PHP: extension_loaded - Manual
- ↑ PHP: Basics - Manual
- ↑ , and the other characters can be letters or _ or $ or numbers.