Troubleshooting of PHP errors: Difference between revisions

From LemonWiki共筆
Jump to navigation Jump to search
Line 167: Line 167:
=== 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]]
=== Json errors ===
[[Resolve PHP json decode error]]


=== phpgrid:  Couldn't execute query ===
=== phpgrid:  Couldn't execute query ===

Revision as of 14:35, 12 April 2019

PHP 問題的排除與解決

PHP 技術問題處理

檔案操作有關

可否讀取或寫入:例如 imagejpeg($canvas, $filename, 100); 沒有顯示錯誤訊息,則需要

  • 檢查該檔案所在目錄是否已經建立,若未建立則需要建立 mkdir,並設定可以寫入。如果產生位置是在多層子目錄下 (巢狀的多層目錄),則需要啟用 recursive 選項[1]
  • 設定該檔案/目錄是否可以寫入: 如果要刪除或寫入檔案,需要檢查是否具備寫入權限
    1. SELinux (Security-Enhanced Linux) policy: httpd_sys_rw_content_t[2]
    2. (optional) 該檔案/目錄的 (1) 擁有者是網站使用者 (e.g. 網站伺服器設定檔預設值 CentOS 是 apache、Ubuntu 則是 www-data[3]) 、或者是 (2) 網站使用者的群組 (e.g. CentOS 是 apache) 可以寫入
    3. Win Os windows.png File Permissions in Windows (WAMP) [4]
  • 驗證是否具備寫入權限:
    1. 輸入 Linux Os linux.png 指令 (1) 檢查檔案權限 ls -Z /path/to/file、(2) 檢查目錄權限 ls -Zd /path/to/directory/
    2. PHP is_writable function

不知道網站伺服器載入哪一個 php.ini 設定檔

使用 console command[5]

  • 輸入命令 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 確認「Configuration File」[6]: echo "<?php phpinfo(); ?>" | php | grep "Configuration File"
    • 指定完整 php 路徑 command: echo "<?php phpinfo(); ?>" | /Applications/XAMPP/bin/php | grep "Configuration File"
  • php -i | grep "Configuration File"

執行PHP時顯示原始碼的錯誤

確認伺服器是否能執行 PHP

  • 驗證方式:
    • 網頁伺服器放置寫了 phpinfo 的 PHP 檔案,看是否可以顯示結果。使用後建議移除該檔案,避免對外揭露伺服器環境資訊。或
    • php -v 如果可以顯示 PHP 版本資訊,代表有安裝 PHP 成功。
  • 解決方式:
    • 不能執行 PHP 的話,需要檢查 安裝 PHP 步驟。

如果 PHP 使用 short tag 語法撰寫,但是沒有啟用 short_open_tag ,會造成顯示原始碼的錯誤。

  • 驗證方式:
    • 輸入指令 php -i | grep short_open_tag 確認結果為 short_open_tag = Off
  • 解決方式:
    • 法1: 啟用 short_open_tag (1) php.ini 檔案 需要開啟 short_open_tag = Off -> On (2) 重新啟動網頁伺服器服務,讓 php.ini 修改生效 (3) 驗證 short_open_tag = On
    • 法2: 不啟用 short_open_tag,將多個 PHP 檔案的 <? 改成 <?php 。 (1) 使用支援 Regular expression 的文字編輯軟體、(2) 搜尋 <\?\s 取代為 <\?php 。請注意取代部分結尾有一個空白。詳見 Batch remove PHP short tags

錯誤訊息: 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 Os linux.png
    • 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 列出載入的模組[7]

錯誤訊息: 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 Os linux.png

預期結果:

OpenSSL support => enabled

預期結果:

# 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

相關頁面: Email testing

錯誤訊息: 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) [8]
  • 原因: 一次讀取13萬行的資料,發生錯誤等原因
  • 解決方法:
    • 增加 memory_limit[9]
    • 跟檔案處理有關: (1) 減少每次讀取的資料行數,例如每次只讀取 50 行的資料筆數來做處理。 (2) 避免使用一次讀取全部檔案內容的 file_get_contentsfile_put_contents等函數、 (3) 如果透過 MySQL 執行匯出資料表的 CSV 檔案,則可以不要選擇欄位名稱,而是選擇全部欄位直接匯出。原因:「Rather than attempting to build the object-tree, you could directly try to select the result into a file」[10]
    • foreach 時,與其寫入整個陣列到記憶體,可以改用 Generatorsfgets 寫法,節省記憶體的使用。

錯誤訊息: 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);

More on Data handling

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 或 Could not open input file: composer.phar

錯誤訊息: 透過 composer 安裝 PHP 套件時,例如 composer require league/csv,出現錯誤訊息「composer.phar: command not found」或「Could not open input file: composer.phar」

  • 解法I: 如果沒有設定 composer.phar 的 PATH ,需要清楚告知 composer.phar 的完整檔案路徑,例如/path/to/php /path/to/composer require league/csv
  • 解法II on Mac icon_os_mac.png /Linux Os linux.png : 將下載的 composer.phar 移動到 /usr/local/bin/composer mv /path/to/composer.phar /usr/local/bin/composer,再重新執行安裝套件的指令[11]

COMPOSER 升級 PHPUNIT 版本 6 到 7 遇到問題 YOUR REQUIREMENTS COULD NOT BE RESOLVED TO AN INSTALLABLE SET OF PACKAGES

解決 Composer 升級 PHPUnit 版本 6 到 7 遇到問題 Your requirements could not be resolved to an installable set of packages

停止無限迴圈

How can I find out which PHP script a process is running in Linux? - Stack Overflow

ps aux | grep php

command line - How do I find and kill a php loop (process)? - Super User

pkill -9 php

PHP | shell_exec() vs exec() Function - GeeksforGeeks

Or input the kill command to stop the process if you have the permission. See details on Alternative_Linux_commands#Show_the_process_list_.26_kill_the_process

Using PHP from the command line

Execute php script in a bat file

Json errors

Resolve PHP json decode error

phpgrid: Couldn't execute query

PHP Grid Framework 錯誤訊息: Couldn't execute query. You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ...

  • 解法: 查詢語法中包含複雜的 sub query 雖然可以順利呈現查詢結果,但是搜尋篩選時出現查詢錯誤。如果要使用 phpgrid ,建議降低查詢的複雜度。

使用者操作/使用者輸入的內容

Web user behavior

避免的 coding 習慣

  • 避免使用簡化的的變數名稱,例如 $sd 也許一開始還會記得,但是過一陣子就會忘記這是什麼
  • 重複複製貼上的內容,但是內容可能常被使用者更改,導致內容更新困難,需要修改多處的程式碼
  • 絕對路徑或絕對網址寫死在程式碼內,導致日後移機或對外公開網站服務時,需要修改多處的程式碼
    • 存取檔案時將完整路徑,例如 D:/AppServ/www/abc.csv 寫死在程式碼內
    • 將測試網址 (127.0.0.1 或 localhost) 寫死在程式碼內
  • 容易閱讀的錯誤訊息:除了 500 Error ,如果可以讓使用者自行處理,建議改成容易閱讀的錯誤訊息。

unified coding style

variable: $var

  • PHP: starts with dollar symbol $var[12]
  • javascript: the first character can be a letter or _ or $, and the other characters can be letters or _ or $ or numbers.[13]

PHP function and its reversed function

tools

tester

documentation

troubleshooting steps of function

Display error message or check the PHP error logs

Check the Web service logs

  1. sudo tail /var/log/httpd/error.log if the web service logs was located at /var/log/httpd/error.log
  2. Example log: [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
  3. Display partial source code: sed -n '990,110p;111q' /home/wwwroot/path/to/file.php[14]

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.
  • try & catch: PHP: Exceptions

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);

PHP: print_r - Manual

$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

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


Troubleshooting of ...

Template