簡體   English   中英

PHP 和未定義變量策略

[英]PHP and undefined variables strategy

我是一名從 PHP 開始的 C++ 程序員。 我發現由於未定義的變量,我失去了大部分調試時間(以及我的自尊!)。 據我所知,處理它們的唯一方法是在執行時觀察輸出。

是否有其他策略可以更早地注意到這些錯誤(類似於 C++,一次編譯即可提供您需要的所有線索)?

這是 PHP 的常見抱怨。 這里有一些想法:

  1. 使用代碼分析工具 許多 IDE(例如NetBeans)也會有所幫助。

  2. 只需運行代碼。 PHP 沒有像 C++ 那樣昂貴的編譯步驟。

  3. 使用單元測試。 常見的副作用包括: 更好的代碼。

  4. 在您的ini 文件中設置error_reporting(-1)或等效項。

  5. 獲取xdebug 這不是預防性的,但堆棧跟蹤有助於消除錯誤。

  6. isset()=== null (身份運算符)和保護子句是您的朋友。

松散和動態類型是該語言的一個特性。 僅僅因為 PHP對輸入嚴格並不意味着你不能。 如果它真的困擾你並且你有選擇,你可以嘗試改用 Python——它對打字更嚴格一些。

將您的 E_NOTICE 消息記錄到文本文件中。 然后,您可以使用自動腳本處理日志以指示引發這些的文件和行。

不可以。在 PHP 中,您只能在嘗試訪問某個變量時才知道該變量不存在。

考慮:

if ($data = file('my_file.txt')) {
    if (count($data) >= 0)
        $line = reset($data);
}
var_dump($line);

您必須重構代碼,以便所有代碼路徑都指向定義的變量,例如:

$line = "default value";
if ($data = file('my_file.txt')) {
    if (count($data) >= 0)
        $line = reset($data);
}
var_dump($line);

如果沒有任何有意義的默認值,這仍然比isset更好,因為如果最終if中的變量名稱有拼寫錯誤,您會發出警告:

$line = null;
if ($data = file('my_file.txt')) {
    if (count($data) >= 0)
        $line = reset($data);
}
if ($line !== null) { /* ... */ }

當然,您可以使用isset 1在給定點檢查變量是否存在。 但是,如果您的代碼依賴於此,則它的結構可能很差。 我的觀點是,與例如 C/Java 不同,您不能在編譯時確定對變量的訪問是否有效。 PHP 中不存在塊作用域使情況變得更糟。

1嚴格來說, isset不會告訴你一個變量是否被設置,它會告訴你它是否被設置並且不為空。 否則,您將需要get_defined_vars

據我所知,處理它們的唯一方法是在執行時觀察輸出。

不是真的:為了防止這些通知彈出,您只需要確保在第一次訪問變量之前初始化它們。 我們(遺憾的是 IMO)在 PHP 中沒有變量聲明,但是在代碼塊的開頭初始化它們也一樣:

$my_var = value;

使用 phpDocumentor 語法,您還可以將它們聲明為某種類型,至少以許多 IDE 能夠使用以下方式進行代碼查找的方式:

/** @desc optional description of what the variable does
    @var int */
$my_var = 0;

此外,在嘗試訪問變量之前,您可以(有時需要)使用isset() / empty() / array_key_exists()條件。

我同意這有時很糟糕,但這是必要的。 在完成的生產代碼中不應該有任何通知——即使顯示它們被關閉,它們也會消耗性能,而且它們對於找出使用變量時可能出現的錯別字非常有用。 (但你已經知道了。)

第一次使用時注意不要進行需要變量值的操作,例如連接運算符.=

如果您是 C++ 程序員,則必須使用它來聲明所有變量。 如果您想使用它們,可以通過將變量歸零或創建空數組來在 PHP 中執行類似的操作。

注意用戶輸入,並確保您已注冊globals off並通過 isset() 檢查來自 $_GET 和 $_POST 的輸入。

您還可以嘗試根據結構代碼對類進行編碼,並在具有正確隱私策略的類聲明的開頭創建每個變量。

您還可以將應用程序邏輯與視圖分離,通過准備所有必須首先輸出的變量,當它顯示它時,您將知道您准備了哪些變量。

在開發階段使用

error_reporting(E_ALL);

這將顯示導致的每個錯誤,所有 NOTICE 錯誤等。

還要注意您的error_log 這將向您顯示錯誤。

使用錯誤報告系統,例如:

http://php.net/manual/en/function.set-error-handler.php

class ErrorReporter
{
    public function catch($errno, $errstr, $errfile, $errline)
    {
        if($errno == E_USER_NOTICE && !defined('DEBUG'))
        {
            // Catch all output buffer and clear states, redirect or include error page.
        }
    }
}

set_error_handler(array(new ErrorReporter,'catch'));

其他一些提示總是對您可能/可能由於if語句而未設置的變量使用isset

始終使用if(isset($_POST['key']))或者甚至更好地使用if(!empty($_POST['key']))因為它檢查鍵是否存在以及值是否不為空。

確保您也了解比較運算符。 像 C# 這樣的語言使用==來檢查布爾狀態,而在 PHP 中要檢查數據類型,您必須使用===並使用==來檢查值狀態,並使用單個=來分配值!

除非我遺漏了什么,那么為什么沒有人建議正確構建您的頁面? 我從來沒有真正遇到過未定義變量錯誤的持續問題。

關於構建頁面的想法

在頂部定義所有變量,必要時分配默認值,然后從那里使用這些變量。 這就是我編寫網頁的方式,我從來沒有遇到未定義的變量問題。

不要養成只在需要時才定義變量的習慣。 這會很快創建意大利面條式代碼並且可能非常難以管理。

替代文字

沒有人喜歡意大利面條式代碼

如果您向我們展示您的一些代碼,我們或許能夠提供有關如何更好地構建代碼以解決此類錯誤的建議。 來自 C 背景的您可能會感到困惑; 該流程可能與網頁不同。

好的做法是在使用前定義所有變量,即設置一個默認值:

$variable = default_value;

這將解決大多數問題。 如前所述,在NetBeans 等編輯器中使用Xdebug或內置調試工具。

如果要隱藏未定義變量的錯誤,請使用@ 示例: @$var

我相信可用於 PHP 的各種代碼覆蓋率工具將突出這一點。

就我個人而言,我嘗試設置變量,即使它帶有空字符串、數組、布爾值等。然后我在使用它們之前使用諸如isset()類的函數。 例如:

$page_found = false;

if ($page_found==false) {
    // Do page not found stuff here
}

if (isset($_POST['field'])) {
    $value = $_POST['field'];
    $sql = "UPDATE table SET field = '$value'";
}

等等。 在一些聰明人說出來之前:我知道該查詢是不安全的。 這只是使用isset()一個例子。

我真的沒有在這里找到直接的答案。 我發現這個問題的實際解決方案是使用PHP Code Sniffer和這個名為PHP Code Sniffer Variable Analysis 的很棒的擴展。

此外,常規 PHP linter (php -l) 可在 PHP Code Sniffer 中使用,因此我正在考慮為常規 PHP linting 自定義配置、檢測未使用/未初始化的變量並驗證我自己的代碼樣式,所有這些只需一步即可。

我非常小的 PHPCS 配置:

<?xml version="1.0"?>
<ruleset name="MyConfig">
    <description>Minimal PHP Syntax check</description>
    <rule ref="Generic.PHP.Syntax" />
    <rule ref="VariableAnalysis" />
</ruleset>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM