首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 易混淆知識點總結:echo/print、include/require、空值判斷、===、self::/$this->、strstr/strpos、HTTP_HOST/SERVER_NAME

     編輯:PHP 相關知識

PHP 易混淆知識點總結:echo/print、include/require、空值判斷、===、self::/$this->、strstr/strpos、HTTP_HOST/SERVER_NAME

PHP 開發中有許多「看似相同、實則大不同」的概念,搞混它們會導致邏輯錯誤、性能損耗、安全漏洞。本文系統梳理 9 對高頻易混淆點,給出語法規則、底層差異、最佳實踐與避坑案例,助你寫出更精準、健壯的代碼。

1. echo vs print

特性echoprint
類型語言結構語言結構 (表現為函數)
返回值無 (void)總是 1 (int)
參數多參數 echo $a, $b (無逗號則串聯)單參數 print $a
表達式使用不可 $x = echo 1 ❌可 $x = print "hi"; // $x=1 ✅
性能略快 (無返回值開銷)略慢

最佳實踐: 純輸出用 echo (或 模板標籤);需在表達式中輸出並用返回值時用 print。

2. include vs require (_once)

特性includerequire
載入時機運行期 (執行到該行)編譯期 (腳本啟動前)
失敗後果E_WARNING,腳本繼續E_COMPILE_ERROR,腳本終止
條件載入支援 if ($cond) include 'a.php';不支援 (編譯期已載入),條件判斷無效
_once 變體防重複載入,維護已載入表同理

避坑: require 在循環/條件中**不會**動態載入不同文件,需用 include。現代框架均用 Composer 自動加載,**極少直接用 include/require**。

3. 空字符串 ''、null、0、false、[] 判斷陷阱

<?php
$vars = [
    'empty_str' => '',
    'null'      => null,
    'zero_int'  => 0,
    'zero_str'  => '0',
    'false'     => false,
    'empty_arr' => [],
];

foreach ($vars as $name => $val) {
    echo "$name: ";
    echo "empty=" . (empty($val) ? 'T' : 'F');
    echo " isset=" . (isset($val) ? 'T' : 'F');
    echo " bool=" . ((bool)$val ? 'T' : 'F');
    echo " ==null=" . ($val == null ? 'T' : 'F');
    echo " ===null=" . ($val === null ? 'T' : 'F');
    echo "\n";
}
/* 輸出關鍵差異:
empty_str : empty=T isset=T bool=F ==null=T ===null=F
null      : empty=T isset=F bool=F ==null=T ===null=T
zero_int  : empty=T isset=T bool=F ==null=T ===null=F
zero_str  : empty=T isset=T bool=F ==null=T ===null=F  ⚠️ '0' 視為空!
false     : empty=T isset=T bool=F ==null=T ===null=F
empty_arr : empty=T isset=T bool=F ==null=T ===null=F
*/

鐵律:

  • empty():""、0、"0"、null、false、[] 全為 true。**業務主鍵 ID 為 0 時慎用**。
  • isset():僅檢查變量**存在且不為 null**。isset($arr['key']) 判斷鍵存在。首選判斷變量/數組鍵是否設置。
  • === null:精確判斷 null。
  • (bool)$val:邏輯判斷轉換。

4. == (等值) vs === (全等/恆等)

<?php
var_dump('' == null);    // true  ⚠️
var_dump('' === null);   // false ✅
var_dump(0 == 'abc');    // true  ⚠️ 'abc' 轉數字為 0
var_dump(0 === 'abc');   // false ✅
var_dump(false == '0');  // true  ⚠️
var_dump(false === '0'); // false ✅

規則: == 觸發類型轉換 (轉數字或布爾),=== 同時比較類型與值。**嚴格模式下 (declare(strict_types=1)) 僅影響函數參數/返回類型,不影響 ==/=== 行為**。
最佳實踐: **默認使用 ===**,除非明確需要類型轉換語義 (如 $_GET['id'] == 0 兼容字符串 "0")。

5. self:: vs $this-> (靜態/類屬性 vs 實例屬性)

<?php
class Demo {
    const CONST_VAL = 'C';
    public static $staticProp = 'S';
    public $instanceProp = 'I';

    public static function staticMethod() {
        echo self::CONST_VAL;      // ✅ 訪問常量
        echo self::$staticProp;    // ✅ 訪問靜態屬性
        // echo $this->instanceProp; // ❌ 靜態方法無 $this
    }

    public function instanceMethod() {
        echo self::CONST_VAL;      // ✅
        echo self::$staticProp;    // ✅
        echo $this->instanceProp;  // ✅ 訪問實例屬性
        // echo $this::CONST_VAL;    // ❌ 語法錯誤
    }
}

規則:

  • self:: (或 ClassName::) 訪問:**常量、靜態屬性、靜態方法**。
  • $this-> 訪問:**實例屬性、實例方法**。
  • 晚期靜態綁定 (LSB): 繼承場景下 static:: 解析為調用類,self:: 解析為定義類。static::method() 實現多態靜態調用。

6. strstr/stristr vs strpos/stripos

函數返回值大小寫性能用途
strstr針頭位置到末尾的字符串敏感較慢 (分配新字符串)需要子串內容
stristr同上不敏感較慢同前
strpos整數位置 (0-based),未找到 false敏感最快 (僅返回偏移)僅判斷是否包含
stripos同上不敏感快同前

避坑: if (strpos($hay, $needle)) **錯誤**!位置 0 會被當作 false。必須 if (strpos($hay, $needle) !== false) 或 if (str_contains($hay, $needle)) (PHP 8+)。

7. HTTP_HOST vs SERVER_NAME

場景HTTP_HOSTSERVER_NAME
來源請求 Header Host (客戶端可控)Web 服務器配置 ServerName (服務端可控)
含端口是 (非標準端口)否
反向代理可能為內網 IP/端口通常為公網域名
可信度低 (可偽造)高
推薦用法生成給用戶看的鏈接、CORS Origin內部邏輯判斷、安全驗證、生成絕對 URL

最佳實踐: 關鍵業務 (支付回調域名驗證、生成分享鏈接) 用 SERVER_NAME 或配置常量 APP_DOMAIN;HTTP_HOST 僅用於顯示/非安全場景。端口映射/內網穿透環境優先 HTTP_X_FORWARDED_HOST。

8. array_merge vs + (數組合併)

<?php
$a = ['a' => 1, 'b' => 2];
$b = ['b' => 3, 'c' => 4];

var_dump(array_merge($a, $b)); // ['a'=>1, 'b'=>3, 'c'=>4] 數字鍵重新索引
var_dump($a + $b);             // ['a'=>1, 'b'=>2, 'c'=>4] 字符串鍵後者不覆蓋,數字鍵同理

規則: array_merge:字符串鍵後覆蓋前,數字鍵**重新索引從 0 開始**。+:鍵衝突時**保留第一個**,不重新索引。

9. define() vs const (常量定義)

特性define()const
作用域全局 (命名空間下)類常量/命名空間常量 (編譯期)
值類型任意表達式 (函數調用、變量)編譯期常量表達式 (標量、數組 PHP 7+、常量)
大小寫敏感可選 define('FOO', 1, true) 不敏感嚴格敏感
性能運行期解析編譯期解析,更快

最佳實踐: 類常量用 const;全局配置常量用 const (命名空間下);動態值 (如版本號從文件讀取) 用 define()。

總結速查卡

場景推薦選擇核心理由
輸出變量echo / 無返回值開銷、多參數支援
載入文件Composer Autoload標準化、性能、避免 include/require 坑
判斷變量存在isset()不視 0/false/'' 為未設置
判斷空值=== null / !== null精確、無類型轉換
比較值===類型安全、可預測
訪問類常量/靜態self:: / static:: (LSB)語法規定
判斷包含子串strpos !== false / str_contains (PHP 8+)性能最好、語義清晰
獲取可信域名SERVER_NAME / 常量 APP_DOMAIN不可偽造
合併配置數組array_merge (字符串鍵覆蓋) 或 + (保留首個)按語義選擇

結語

這 9 對易混淆點覆蓋了 PHP 開發 80% 的「隱性 Bug 來源」。建議將速查卡打印貼在工位,Code Review 時重點檢查。隨著 PHP 8.1/8.2/8.3 新特性 (str_contains, array_is_list, never 返回類型, readonly 屬性) 推出,部分舊坑被語言層面修復,**保持版本升級、啟用嚴格模式、使用靜態分析 (PHPStan/Psalm)** 是從根本上規避此類問題的長效機制。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved