Troubleshooting of PHP errors: Difference between revisions

Tag: wikieditor
Tag: wikieditor
 
(7 intermediate revisions by the same user not shown)
Line 1: Line 1:
PHP 技術問題的排除與解決
PHP 技術問題的排除與解決


=== 檢查步驟 ===
This article categorizes various PHP issues into four main types:


# 檢查 PHP log
# '''File and Directory Issues''': These involve problems related to file handling and directory operations in PHP, such as file not found errors or issues with file permissions.
# '''Configuration and Environment Issues''': This category covers issues arising from misconfigurations or environmental factors, including PHP settings, memory limits, and server configurations.
# '''Error Handling and Debugging''': These issues pertain to errors and debugging challenges, such as syntax errors, runtime errors, and debugging messages.
# '''General PHP Practices''': This encompasses best practices and general usage of PHP, including coding standards, command-line usage, and avoiding common pitfalls.
 
== Troubleshooting steps of PHP errors ==
Display error message or check the PHP error logs
* {{kbd | key=<nowiki>ini_set("display_errors", "On");</nowiki>}} See details on [http://php.net/manual/en/errorfunc.configuration.php PHP: Runtime Configuration - Manual]
* {{kbd | key=<nowiki>error_reporting(E_ALL);</nowiki>}} See details on [http://php.net/manual/en/function.error-reporting.php PHP: error_reporting - Manual]
* [https://www.jetbrains.com/help/phpstorm/event-log-tool-window.html Event Log - Help | PhpStorm]
 
Check the Web service logs
# {{kbd | key=<nowiki>sudo tail /var/log/httpd/error.log</nowiki>}} if the web service logs was located at {{kbd | key=<nowiki>/var/log/httpd/error.log</nowiki>}}
# Example log: {{kbd | key=<nowiki>[Thu Nov 08 12:20:40.412630 2018] [:error] [pid 12769] [client x.x.x.x:4433] PHP Parse error:  syntax error, unexpected '$var' (T_VARIABLE) in /home/wwwroot/path/to/file.php on line 100</nowiki>}}
# Display partial source code: {{kbd | key=<nowiki>sed -n '990,110p;111q' /home/wwwroot/path/to/file.php</nowiki>}}<ref>[https://stackoverflow.com/questions/83329/how-can-i-extract-a-predetermined-range-of-lines-from-a-text-file-on-unix How can I extract a predetermined range of lines from a text file on Unix? - Stack Overflow]</ref>
# 檢查網站伺服器 error log e.g. 如果使用 [https://www.nginx.com/ NGINX] Web Server 可輸入指令 {{kbd | key=<nowiki>sudo tail /var/log/nginx/error.log</nowiki>}}
# 檢查網站伺服器 error log e.g. 如果使用 [https://www.nginx.com/ NGINX] Web Server 可輸入指令 {{kbd | key=<nowiki>sudo tail /var/log/nginx/error.log</nowiki>}}
Simply the question
* Is the [http://php.net/manual/en/function.function-exists.php 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 [http://php.net/manual/en/function.var-dump.php var_dump] or [http://php.net/manual/en/function.print-r.php print_r] functions.
* Check the if-else condition was satisfied or not cf: [http://www.leepoint.net/notes-java/data/strings/12stringcomparison.html Java: String Comparison] It's logical (compiler will not show the warning) but wrong.
* try & catch: [http://php.net/manual/en/language.exceptions.php PHP: Exceptions]
=== logging ===
native error logging
* [http://www.php.net/ PHP] log: check the configuration file: /etc/php.ini (the location of configuration file can be verified by [http://php.net/manual/en/function.phpinfo.php phpinfo()] )
(for production site) unmark theese lines in the php.ini and restart Apache service
<pre>
log_errors = On
error_log = "php_error.log"
</pre>
(for development site) using [http://php.net/manual/en/function.error-reporting.php error_reporting]
<pre>
error_reporting(E_ALL);
</pre>
[http://tw1.php.net/print_r PHP: print_r - Manual]
<pre>
$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
</pre>
capture the result of var_dump:
ob_start
* [http://stackoverflow.com/questions/139474/how-can-i-capture-the-result-of-var-dump-to-a-string php - How can I capture the result of var_dump to a string? - Stack Overflow]
* [http://php.net/manual/en/function.error-log.php PHP: error_log - Manual]
<pre>
ob_start();
var_dump($some_variable);
$result = ob_get_clean();
error_log($result, 3, 'd:/result.log');
</pre>
QuickForm
<pre>
$result = var_dump($some_variable);
$form->addElement('html', $result);
</pre>
[http://ellislab.com/codeigniter CodeIgniter]: [http://stackoverflow.com/questions/7370391/how-to-configure-codeigniter-to-report-all-errors php - How to configure Codeigniter to report all errors? - Stack Overflow]
show the line number and filename
<pre>
echo 'Houston, we've had a problem '. __line__ . ' ' . __FILE__ ."<br />";
</pre>
more on [http://php.net/manual/en/language.constants.predefined.php PHP: Magic constants], [https://github.com/Seldaek/monolog monolog]
== File and Directory Issues ==
=== 檔案操作有關 ===
可否讀取或寫入:例如 imagejpeg($canvas, $filename, 100); 沒有顯示錯誤訊息,則需要
* 檢查檔案或目錄是否存在 [http://tw2.php.net/file_exists file_exists]
* 檢查檔案是否可以讀取 [http://php.net/manual/en/function.is-readable.php is_readable]
* 如果是上傳檔案,需要檢查暫存目錄是否可以寫入 [http://stackoverflow.com/questions/1520956/php-way-to-find-the-web-servers-temp-path upload - PHP way to find the web server's temp path? - Stack Overflow]
* 檢查該檔案所在目錄是否已經建立,若未建立則需要建立 [http://php.net/manual/en/function.mkdir.php mkdir],並設定可以寫入。如果產生位置是在多層子目錄下 (巢狀的多層目錄),則需要啟用 recursive 選項<ref>[http://stackoverflow.com/questions/2303372/create-a-folder-if-it-doesnt-already-exist php - Create a folder if it doesn't already exist - Stack Overflow]  code snippet: <nowiki>mkdir('path/to/directory', 0755, true);</nowiki> </ref>
* 設定該檔案/目錄是否可以寫入: 如果要刪除或寫入檔案,需要檢查是否具備寫入權限
*# SELinux (Security-Enhanced Linux) policy: {{kbd | key = httpd_sys_rw_content_t}}<ref>[https://blog.lysender.com/2015/07/centos-7-selinux-php-apache-cannot-writeaccess-file-no-matter-what/ CentOS 7 + SELinux + PHP + Apache – cannot write/access file no matter what | Lysender's Daily Log Book]</ref>
*# (optional) 該檔案/目錄的 (1) 擁有者是網站使用者 (e.g. 網站伺服器設定檔預設值 CentOS 的 Apache 伺服器是 apache、Ubuntu 的 Apache 伺服器則是 www-data<ref>[https://ubuntuforums.org/showthread.php?t=1293508 [SOLVED] How to find out Apache Username?]</ref>) 、或者是 (2) 網站使用者的群組 (e.g. CentOS 的 Apache 伺服器是 apache、Nginx 伺服器是 nginx) 可以寫入
*# {{Win}} [http://www.webdeveloper.com/forum/showthread.php?165933-File-Permissions-in-Windows-(WAMP) File Permissions in Windows (WAMP)] <ref>[https://technet.microsoft.com/en-us/library/Cc754344.aspx Set, View, Change, or Remove Permissions on Files and Folders]</ref>
* 驗證是否具備寫入權限:
*# 輸入 {{Linux}} 指令 (1) 檢查檔案權限 {{kbd | key = ls -Z /path/to/file}}、(2) 檢查目錄權限 {{kbd | key = ls -Zd /path/to/directory/}}
*# PHP [https://www.php.net/manual/en/function.get-current-user.php get_current_user] function
*# PHP [http://php.net/manual/en/function.is-writable.php is_writable function]
=== 錯誤訊息: no such file or directory 找不到 PHP 路徑 ===
<pre>
% php -v
zsh: no such file or directory: /Applications/MAMP/bin/php/php7.4.21/bin/php
</pre>
解決方法:找到 PHP 檔案路徑
* [[XAMPP]] on {{Mac}} {{kbd | key=<nowiki>/Applications/xampp/bin/php</nowiki>}}
* MAMP PRO on on {{Mac}} input the command ls {{kbd | key=<nowiki>/Applications/MAMP/bin/php/php*/bin/php</nowiki>}} to find the suitable version you want e.g. {{kbd | key=<nowiki>/Applications/MAMP/bin/php/php8.1.13/bin/php</nowiki>}}
If you are using zsh. Input the command {{kbd | key=<nowiki>vi ~/.zshrc</nowiki>}} to edit the file<ref>[https://castion2293.medium.com/mac%E4%B8%AD%E5%8D%87%E7%B4%9Aphp%E7%89%88%E6%9C%AC%E4%B8%A6%E8%A8%AD%E7%82%BA%E9%A0%90%E8%A8%AD-d7e6fdad9cc2 Mac中升級php版本並設為預設. 確認目前PHP的版本 | by Nick Zhang | Medium]</ref>
原檔案內容
<pre>
alias php='/Applications/MAMP/bin/php/php7.4.21/bin/php'
</pre>
修改後檔案內容
<pre>
alias php='/Applications/MAMP/bin/php/php8.1.13/bin/php'
</pre>
And then relaunch the shell
=== PHPExcel 產生的 Excel 檔案,開啟後看到一堆亂碼 ===
狀況1: 開啟 Excel 檔案,看到最前面有 {{kbd | key=<nowiki>NOTICE</nowiki>}} 的錯誤訊息,例如 {{kbd | key=<nowiki><b>Notice</b>:  Constant CONST_XXX already defined in <b>path\to\script.php</b> on line xx</nowiki>}}
* 解法: 關閉錯誤訊息輸出 ex: [http://www.php.net/manual/en/function.error-reporting.php error_reporting(0);] 以及修正 NOTICE 訊息指涉的問題,例如例子中常數重複宣告的問題。
狀況2: 開啟 Excel 檔案,看到最前面有 {{kbd | key=<nowiki>Fatal error</nowiki>}} 之類的錯誤訊息
* 解法: 關閉錯誤訊息輸出 ex: [http://www.php.net/manual/en/function.error-reporting.php error_reporting(0);] ,以及修正 Fatal error 訊息指涉的問題。
狀況3: 開啟 Excel 檔案,看到有儲存格位址之類的錯誤訊息
* 解法: 該儲存格內容以等號 (=) 開始,卻不是函數。解決方式是將儲存格內容的最前面加一個單引號 (') 或者是加個空白。


== Configuration and Environment Issues ==
== Configuration and Environment Issues ==
=== 不知道網站伺服器載入哪一個 php.ini 設定檔 ===
=== 不知道網站伺服器載入哪一個 php.ini 設定檔 ===
使用 console command<ref>[http://php.net/manual/en/features.commandline.options.php PHP: Options - Manual]</ref>
使用 console command<ref>[http://php.net/manual/en/features.commandline.options.php PHP: Options - Manual]</ref>
* 輸入命令 {{kbd | key = <nowiki>php --ini</nowiki>}} 或 {{kbd | key = <nowiki>/complete/path/to/php --ini</nowiki>}}
* 輸入命令 {{kbd | key = <nowiki>php --ini</nowiki>}} 或 {{kbd | key = <nowiki>/path/to/php --ini</nowiki>}}
<pre>
<pre>
> php --ini
> php --ini
Line 94: Line 223:
* 解法I: 如果沒有設定 composer.phar 的 PATH ,需要清楚告知 composer.phar 的完整檔案路徑,例如{{kbd | key = /path/to/php /path/to/composer require league/csv}}
* 解法I: 如果沒有設定 composer.phar 的 PATH ,需要清楚告知 composer.phar 的完整檔案路徑,例如{{kbd | key = /path/to/php /path/to/composer require league/csv}}
* 解法II on {{Mac}}/{{Linux}}:  將下載的 composer.phar 移動到 /usr/local/bin/composer {{kbd | key = mv /path/to/composer.phar /usr/local/bin/composer}},再重新執行安裝套件的指令<ref>[http://stackoverflow.com/questions/21670709/running-composer-returns-could-not-open-input-file-composer-phar php - Running Composer returns: "Could not open input file: composer.phar" - Stack Overflow]</ref>。
* 解法II on {{Mac}}/{{Linux}}:  將下載的 composer.phar 移動到 /usr/local/bin/composer {{kbd | key = mv /path/to/composer.phar /usr/local/bin/composer}},再重新執行安裝套件的指令<ref>[http://stackoverflow.com/questions/21670709/running-composer-returns-could-not-open-input-file-composer-phar php - Running Composer returns: "Could not open input file: composer.phar" - Stack Overflow]</ref>。
== File and Directory Issues ==
=== 檔案操作有關 ===
可否讀取或寫入:例如 imagejpeg($canvas, $filename, 100); 沒有顯示錯誤訊息,則需要
* 檢查檔案或目錄是否存在 [http://tw2.php.net/file_exists file_exists]
* 檢查檔案是否可以讀取 [http://php.net/manual/en/function.is-readable.php is_readable]
* 如果是上傳檔案,需要檢查暫存目錄是否可以寫入 [http://stackoverflow.com/questions/1520956/php-way-to-find-the-web-servers-temp-path upload - PHP way to find the web server's temp path? - Stack Overflow]
* 檢查該檔案所在目錄是否已經建立,若未建立則需要建立 [http://php.net/manual/en/function.mkdir.php mkdir],並設定可以寫入。如果產生位置是在多層子目錄下 (巢狀的多層目錄),則需要啟用 recursive 選項<ref>[http://stackoverflow.com/questions/2303372/create-a-folder-if-it-doesnt-already-exist php - Create a folder if it doesn't already exist - Stack Overflow]  code snippet: <nowiki>mkdir('path/to/directory', 0755, true);</nowiki> </ref>
* 設定該檔案/目錄是否可以寫入: 如果要刪除或寫入檔案,需要檢查是否具備寫入權限
*# SELinux (Security-Enhanced Linux) policy: {{kbd | key = httpd_sys_rw_content_t}}<ref>[https://blog.lysender.com/2015/07/centos-7-selinux-php-apache-cannot-writeaccess-file-no-matter-what/ CentOS 7 + SELinux + PHP + Apache – cannot write/access file no matter what | Lysender's Daily Log Book]</ref>
*# (optional) 該檔案/目錄的 (1) 擁有者是網站使用者 (e.g. 網站伺服器設定檔預設值 CentOS 的 Apache 伺服器是 apache、Ubuntu 的 Apache 伺服器則是 www-data<ref>[https://ubuntuforums.org/showthread.php?t=1293508 [SOLVED] How to find out Apache Username?]</ref>) 、或者是 (2) 網站使用者的群組 (e.g. CentOS 的 Apache 伺服器是 apache、Nginx 伺服器是 nginx) 可以寫入
*# {{Win}} [http://www.webdeveloper.com/forum/showthread.php?165933-File-Permissions-in-Windows-(WAMP) File Permissions in Windows (WAMP)] <ref>[https://technet.microsoft.com/en-us/library/Cc754344.aspx Set, View, Change, or Remove Permissions on Files and Folders]</ref>
* 驗證是否具備寫入權限:
*# 輸入 {{Linux}} 指令 (1) 檢查檔案權限 {{kbd | key = ls -Z /path/to/file}}、(2) 檢查目錄權限 {{kbd | key = ls -Zd /path/to/directory/}}
*# PHP [https://www.php.net/manual/en/function.get-current-user.php get_current_user] function
*# PHP [http://php.net/manual/en/function.is-writable.php is_writable function]
=== 錯誤訊息: no such file or directory 找不到 PHP 路徑 ===
<pre>
% php -v
zsh: no such file or directory: /Applications/MAMP/bin/php/php7.4.21/bin/php
</pre>
解決方法:找到 PHP 檔案路徑
* [[XAMPP]] on {{Mac}} {{kbd | key=<nowiki>/Applications/xampp/bin/php</nowiki>}}
* MAMP PRO on on {{Mac}} input the command ls {{kbd | key=<nowiki>/Applications/MAMP/bin/php/php*/bin/php</nowiki>}} to find the suitable version you want e.g. {{kbd | key=<nowiki>/Applications/MAMP/bin/php/php8.1.13/bin/php</nowiki>}}
If you are using zsh. Input the command {{kbd | key=<nowiki>vi ~/.zshrc</nowiki>}} to edit the file<ref>[https://castion2293.medium.com/mac%E4%B8%AD%E5%8D%87%E7%B4%9Aphp%E7%89%88%E6%9C%AC%E4%B8%A6%E8%A8%AD%E7%82%BA%E9%A0%90%E8%A8%AD-d7e6fdad9cc2 Mac中升級php版本並設為預設. 確認目前PHP的版本 | by Nick Zhang | Medium]</ref>
原檔案內容
<pre>
alias php='/Applications/MAMP/bin/php/php7.4.21/bin/php'
</pre>
修改後檔案內容
<pre>
alias php='/Applications/MAMP/bin/php/php8.1.13/bin/php'
</pre>
And then relaunch the shell
=== PHPExcel 產生的 Excel 檔案,開啟後看到一堆亂碼 ===
狀況1: 開啟 Excel 檔案,看到最前面有 {{kbd | key=<nowiki>NOTICE</nowiki>}} 的錯誤訊息,例如 {{kbd | key=<nowiki><b>Notice</b>:  Constant CONST_XXX already defined in <b>path\to\script.php</b> on line xx</nowiki>}}
* 解法: 關閉錯誤訊息輸出 ex: [http://www.php.net/manual/en/function.error-reporting.php error_reporting(0);] 以及修正 NOTICE 訊息指涉的問題,例如例子中常數重複宣告的問題。
狀況2: 開啟 Excel 檔案,看到最前面有 {{kbd | key=<nowiki>Fatal error</nowiki>}} 之類的錯誤訊息
* 解法: 關閉錯誤訊息輸出 ex: [http://www.php.net/manual/en/function.error-reporting.php error_reporting(0);] ,以及修正 Fatal error 訊息指涉的問題。
狀況3: 開啟 Excel 檔案,看到有儲存格位址之類的錯誤訊息
* 解法: 該儲存格內容以等號 (=) 開始,卻不是函數。解決方式是將儲存格內容的最前面加一個單引號 (') 或者是加個空白。


== Error Handling and Debugging ==
== Error Handling and Debugging ==
Line 233: Line 304:
=== Using PHP from the command line ===
=== Using PHP from the command line ===
[[Execute php script in a bat file]]
[[Execute php script in a bat file]]
=== 移除非預期的空白(全形空白) ===
需要額外移除 [http://www.fileformat.info/info/unicode/char/3000/index.htm 'IDEOGRAPHIC SPACE' (U+3000)] 全形空白
<pre>
$string = str_replace(json_decode('"\u3000"'), "", $string);
$string = trim($string);
</pre>
More on: [[Data_cleaning#Remove other string look like whitespace | Remove other string look like whitespace]]


== 使用者操作/使用者輸入的內容 ==
== 使用者操作/使用者輸入的內容 ==
Line 255: Line 335:
* [https://itunes.apple.com/us/app/dash/id449589707?ls=1&mt=12 Dash 3] for {{Mac}}  - API Docs & Snippets. Integrates with Xcode, Alfred, TextWrangler and many more. on the Mac App Store
* [https://itunes.apple.com/us/app/dash/id449589707?ls=1&mt=12 Dash 3] for {{Mac}}  - API Docs & Snippets. Integrates with Xcode, Alfred, TextWrangler and many more. on the Mac App Store
* [http://devdocs.io/ DevDocs API Documentation]
* [http://devdocs.io/ DevDocs API Documentation]
== troubleshooting steps of function ==
Display error message or check the PHP error logs
* {{kbd | key=<nowiki>ini_set("display_errors", "On");</nowiki>}} See details on [http://php.net/manual/en/errorfunc.configuration.php PHP: Runtime Configuration - Manual]
* {{kbd | key=<nowiki>error_reporting(E_ALL);</nowiki>}} See details on [http://php.net/manual/en/function.error-reporting.php PHP: error_reporting - Manual]
* [https://www.jetbrains.com/help/phpstorm/event-log-tool-window.html Event Log - Help | PhpStorm]
Check the Web service logs
# {{kbd | key=<nowiki>sudo tail /var/log/httpd/error.log</nowiki>}} if the web service logs was located at {{kbd | key=<nowiki>/var/log/httpd/error.log</nowiki>}}
# Example log: {{kbd | key=<nowiki>[Thu Nov 08 12:20:40.412630 2018] [:error] [pid 12769] [client x.x.x.x:4433] PHP Parse error:  syntax error, unexpected '$var' (T_VARIABLE) in /home/wwwroot/path/to/file.php on line 100</nowiki>}}
# Display partial source code: {{kbd | key=<nowiki>sed -n '990,110p;111q' /home/wwwroot/path/to/file.php</nowiki>}}<ref>[https://stackoverflow.com/questions/83329/how-can-i-extract-a-predetermined-range-of-lines-from-a-text-file-on-unix How can I extract a predetermined range of lines from a text file on Unix? - Stack Overflow]</ref>
Simply the question
* Is the [http://php.net/manual/en/function.function-exists.php 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 [http://php.net/manual/en/function.var-dump.php var_dump] or [http://php.net/manual/en/function.print-r.php print_r] functions.
* Check the if-else condition was satisfied or not cf: [http://www.leepoint.net/notes-java/data/strings/12stringcomparison.html Java: String Comparison] It's logical (compiler will not show the warning) but wrong.
* try & catch: [http://php.net/manual/en/language.exceptions.php PHP: Exceptions]
== logging ==
native error logging
* [http://www.php.net/ PHP] log: check the configuration file: /etc/php.ini (the location of configuration file can be verified by [http://php.net/manual/en/function.phpinfo.php phpinfo()] )
(for production site) unmark theese lines in the php.ini and restart Apache service
<pre>
log_errors = On
error_log = "php_error.log"
</pre>
(for development site) using [http://php.net/manual/en/function.error-reporting.php error_reporting]
<pre>
error_reporting(E_ALL);
</pre>
[http://tw1.php.net/print_r PHP: print_r - Manual]
<pre>
$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
</pre>
capture the result of var_dump:
ob_start
* [http://stackoverflow.com/questions/139474/how-can-i-capture-the-result-of-var-dump-to-a-string php - How can I capture the result of var_dump to a string? - Stack Overflow]
* [http://php.net/manual/en/function.error-log.php PHP: error_log - Manual]
<pre>
ob_start();
var_dump($some_variable);
$result = ob_get_clean();
error_log($result, 3, 'd:/result.log');
</pre>
QuickForm
<pre>
$result = var_dump($some_variable);
$form->addElement('html', $result);
</pre>
[http://ellislab.com/codeigniter CodeIgniter]: [http://stackoverflow.com/questions/7370391/how-to-configure-codeigniter-to-report-all-errors php - How to configure Codeigniter to report all errors? - Stack Overflow]
show the line number and filename
<pre>
echo 'Houston, we've had a problem '. __line__ . ' ' . __FILE__ ."<br />";
</pre>
more on [http://php.net/manual/en/language.constants.predefined.php PHP: Magic constants], [https://github.com/Seldaek/monolog monolog]


== References ==
== References ==