PHP 基礎雖「基礎」,卻是所有上層框架、架構、效能優化的基石。本文系統梳理 7 大核心模組,提供語法速查、常見陷阱、最佳實踐與現代寫法(PHP 7.4+/8.0+)對照,適合初學者建立正確心智模型,也適合資深開發者快速回顧查漏補缺。
<?php
// 索引陣列(數字鍵,從 0 開始)
$fruits = ['Apple', 'Banana', 'Pineapple']; // PHP 5.4+ 短語法
$fruits[] = 'Orange'; // 自動追加索引
// 關聯陣列(字串鍵)
$person = [
'name' => 'John',
'age' => 30,
'skills' => ['PHP', 'JS', 'Go']
];
// 多維陣列
$users = [
['id' => 1, 'name' => 'Alice'],
['id' => 2, 'name' => 'Bob'],
];
// 僅需值
foreach ($fruits as $fruit) { echo $fruit; }
// 需鍵值
foreach ($person as $key => $value) { echo "$key: $value"; }
// 參考修改原陣列
foreach ($fruits as &$fruit) { $fruit = strtoupper($fruit); }
unset($fruit); // 必須解除參考,否則污染後續迴圈
| 函數 | 用途 | 範例 |
|---|---|---|
count() | 元素個數 | count($arr) |
array_keys() | 取得所有鍵 | array_keys($assoc) |
array_values() | 重建索引 | array_values($sparse) |
array_merge() | 合併(字串鍵後覆蓋前) | array_merge($a, $b) |
array_filter() | 過濾 | array_filter($arr, fn($v) => $v > 10) |
array_map() | 映射轉換 | array_map('strtoupper', $arr) |
array_reduce() | 歸約 | array_reduce($arr, fn($c,$v)=>$c+$v, 0) |
in_array() | 值存在性 | in_array($needle, $arr, true) (嚴格模式) |
array_key_exists() | 鍵存在性 | array_key_exists($key, $arr) |
<?php
declare(strict_types=1);
// 完整型別提示(PHP 7.0+)
function calculate(float $a, float $b, string $operator = '+'): float {
return match ($operator) {
'+' => $a + $b,
'-' => $a - $b,
'*' => $a * $b,
'/' => $b !== 0 ? $a / $b : throw new DivisionByZeroError(),
default => throw new InvalidArgumentException("Unknown operator: $operator"),
};
}
// 可變參數
function sum(int ...$numbers): int {
return array_sum($numbers);
}
// 參考傳遞
function increment(int &$value): void { $value++; }
$multiply = fn(int $a, int $b) => $a * $b; // PHP 7.4+ 箭頭函數(自動捕獲外部變數)
$closure = function (int $x) use ($factor): int { return $x * $factor; }; // 傳統閉包需 use
class User {
public string $name; // 公開
protected string $email; // 繼承類可見
private int $loginAttempts = 0; // 僅本類可見
public readonly string $uuid; // PHP 8.1+ 唯讀屬性(建構子後不可改)
public function __construct(string $name, string $email) {
$this->name = $name;
$this->email = $email;
$this->uuid = (string) \Ramsey\Uuid\Uuid::uuid4();
}
}
class BaseModel {
protected static string $table = 'base';
public static function getTable(): string {
return static::$table; // LSB:調用類的靜態屬性
}
}
class User extends BaseModel {
protected static string $table = 'users';
}
User::getTable(); // 'users' (而非 'base')
| 方法 | 觸發時機 | 用途 |
|---|---|---|
__construct | 實例化 | 初始化、依賴注入 |
__destruct | 銷毀 | 資源釋放、關閉連線 |
__call | 呼叫不可見方法 | 代理、動態方法 |
__get/__set | 存取不可見屬性 | 虛擬屬性、資料轉換 |
__toString | 物件作字串使用 | echo $obj、日誌輸出 |
__invoke | 物件作函數呼叫 | 可呼叫物件、策略模式 |
__serialize/__unserialize | 序列化 (PHP 7.4+) | 自定義序列化格式 |
$name = 'John';
echo "Hello $name"; // 解析變數 → "Hello John"
echo 'Hello $name'; // 原樣輸出 → "Hello $name"
echo 'It\'s OK'; // 單引號內僅需轉義 \' 和 \\
echo "Line1\nLine2"; // 雙引號解析 \n \t 等
| 函數 | 用途 | 注意 |
|---|---|---|
trim() | 去首尾空白 | ltrim()/rtrim() 單側 |
strlen() | 位元組長度 | 中文 3 字節;字元長度用 mb_strlen($str, 'UTF-8') |
substr() | 截取 (位元組) | 中文用 mb_substr($str, 0, 10, 'UTF-8') |
strpos() | 查找位置 | 嚴格比較 !== false;stripos() 不分大小寫 |
str_replace() | 替換 | 支援陣列批次;str_ireplace() 不分大小寫 |
implode() | 陣列合併為字串 | implode(',', $arr) |
explode() | 字串分割為陣列 | explode(',', $str) |
htmlspecialchars() | HTML 轉義 (防 XSS) | 輸出前必呼叫,ENT_QUOTES | ENT_SUBSTITUTE |
// 設定
setcookie('lang', 'zh-TW', [
'expires' => time() + 86400*30,
'path' => '/',
'domain' => '.example.com',
'secure' => true, // 僅 HTTPS
'httponly' => true, // JS 不可讀
'samesite' => 'Lax', // CSRF 防護
]);
// 讀取
$lang = $_COOKIE['lang'] ?? 'en';
// 刪除
setcookie('lang', '', time() - 3600, '/');
// 必須最先呼叫
session_start();
// 讀寫
$_SESSION['user_id'] = 123;
$userId = $_SESSION['user_id'] ?? null;
// 刪除單項
unset($_SESSION['user_id']);
// 銷毀整個 Session
session_destroy(); // 同時需刪除 Cookie:setcookie(session_name(), '', time()-3600);
files (預設)redis / memcached (需 session.save_handler 配置)database (CI3/Laravel 等框架支援)<?php
// 當前時間(時區感知)
$now = new DateTime('now', new DateTimeZone('Asia/Taipei'));
echo $now->format('Y-m-d H:i:s'); // 2024-01-15 14:30:00
// 指定日期解析
$date = DateTime::createFromFormat('Y/m/d', '2024/01/15');
// 修改時間
$now->modify('+1 day');
$now->add(new DateInterval('P1M')); // +1 月
// 差值計算
$diff = $date1->diff($date2);
echo $diff->days; // 總天數
echo $diff->format('%h小時%i分'); // 格式化差值
// 時間戳互轉
$timestamp = $now->getTimestamp(); // 1705300200
$fromTs = (new DateTime())->setTimestamp($timestamp);
// 格式化常用
$now->format('Y-m-d'); // 日期
$now->format('H:i:s'); // 時間
$now->format('c'); // ISO 8601: 2024-01-15T14:30:00+08:00
$now->format('U'); // Unix Timestamp
strtotime('+1 week'); // 一週後
strtotime('first day of next month'); // 下月 1 號
strtotime('last friday'); // 上個週五
strtotime('2024-01-15 14:30'); // 絕對時間
<?php
function divide(int $a, int $b): float {
if ($b === 0) {
throw new InvalidArgumentException('Divisor cannot be zero');
}
return $a / $b;
}
try {
$result = divide(10, 0);
} catch (InvalidArgumentException $e) {
echo "Error: " . $e->getMessage(); // Error: Divisor cannot be zero
// $e->getFile(), $e->getLine(), $e->getTraceAsString()
} catch (Throwable $e) { // 捕獲所有 Error + Exception (PHP 7+)
// 記錄日誌、上報監控
}
abstract class AppException extends Exception {
public function __construct(string $message = '', int $code = 0, ?Throwable $previous = null) {
parent::__construct($message, $code, $previous);
}
}
class UserNotFoundException extends AppException {}
class PaymentFailedException extends AppException {}
// 使用
try {
$user = $repo->find($id) ?? throw new UserNotFoundException("User $id not found");
} catch (UserNotFoundException $e) {
// 專門處理
} catch (AppException $e) {
// 統一處理業務異常
}
set_error_handler(function (int $code, string $msg, string $file, int $line) {
if (error_reporting() & $code) {
throw new ErrorException($msg, 0, $code, $file, $line);
}
});
// 現在觸發 Warning/Notice 會拋出 ErrorException 可被 try-catch 捕獲
這 7 大模組構成了 PHP 開發的「內功心法」。關鍵提醒:
array_* 函數族避免手寫迴圈;嚴格區分索引/關聯語意readonly、private、介面隔離、組合優於繼承mb_* 族date()、mktime() 等舊函數內功扎實,招式自靈。願這份知識體系助你寫出更健壯、更優雅、更易維護的 PHP 代碼。