PHP 是 WordPress 的主要後端語言。即使你未來多半透過後台操作網站,只要想修改佈景主題或開發外掛,就必須能讀懂基本 PHP。本章快速導覽 WordPress 開發最常用的語法與思維。

本章學習目標

掌握 PHP 變數、陣列、條件、迴圈、函式與基本除錯方式,並能把 Copilot 當作輔助工具而不是答案來源。

5.1 PHP 程式語言簡介

PHP 在伺服器端執行,負責產生最後送到瀏覽器的 HTML。WordPress 的文章查詢、模板載入、外掛 Hook 與後台管理都大量使用 PHP。

<?php
$title = 'WP2026';
echo '<h1>' . esc_html($title) . '</h1>';
?>

PHP 與 HTML 混寫

在主題模板中,PHP 常穿插於 HTML 之間。重點是保持輸出安全:顯示文字時使用 esc_html(),顯示網址時使用 esc_url(),顯示屬性時使用 esc_attr()

伺服器端執行流程

當使用者打開 WordPress 網站時,瀏覽器並不會直接看到 PHP 原始碼。伺服器會先執行 PHP,讀取 WordPress 核心、主題與外掛,必要時查詢資料庫,最後輸出 HTML、CSS 與 JavaScript 給瀏覽器。

  1. 瀏覽器送出網址請求。
  2. Web Server 將請求交給 PHP 處理。
  3. WordPress 載入設定、外掛與主題。
  4. WordPress 依網址判斷要查詢哪些內容。
  5. 主題模板輸出 HTML 給瀏覽器。

理解這個流程後,你會更容易判斷錯誤發生在哪一層:是 PHP 語法錯誤、資料庫查詢錯誤、模板輸出錯誤,還是前端樣式問題。

開發階段的錯誤顯示

開發時應該讓錯誤可被追蹤,但正式網站不應直接把錯誤顯示給訪客。常見做法是在 wp-config.php 中啟用記錄:

define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false);

之後可到 wp-content/debug.log 查看錯誤。這比直接在前台顯示錯誤安全,也比較適合追蹤偶發問題。

5.2 變數與基本資料結構

PHP 變數以 $ 開頭。WordPress 開發最常用的資料結構是陣列,常用來存放設定、查詢參數與選項。

$course = [
    'title' => 'WordPress 外掛開發',
    'level' => 'advanced',
    'lessons' => 3,
];

echo esc_html($course['title']);

關聯陣列與查詢參數

WordPress 函式常接受關聯陣列,例如查詢文章時可傳入文章類型、每頁數量與排序方式。這種寫法會在 WP_Queryregister_post_type()wp_enqueue_script() 中反覆出現。

常見資料型別

PHP 常見型別包含字串、整數、浮點數、布林值、陣列、物件與 null。WordPress 從資料庫取出的值常常是字串,所以在比較或計算前要留意型別轉換。

$price = '1200';
$quantity = 2;
$total = (int) $price * $quantity;

$is_featured = true;
$tags = ['wordpress', 'php', 'theme'];

若資料來自使用者輸入,儲存前要先清理;若資料要輸出到畫面,輸出前要轉義。這兩件事不能互相取代。

清理與轉義

  • sanitize_text_field():清理一般文字輸入。
  • absint():轉成非負整數。
  • esc_html():輸出 HTML 文字節點。
  • esc_attr():輸出 HTML 屬性。
  • esc_url():輸出網址。
$name = sanitize_text_field($_POST['name'] ?? '');
echo '<span title="' . esc_attr($name) . '">' . esc_html($name) . '</span>';

5.3 決策指令的應用

條件判斷可根據不同狀態輸出不同內容。WordPress 也提供許多條件式標籤,例如 is_single()is_page()is_front_page()

if (is_single()) {
    echo '<p>這是單篇文章頁。</p>';
} elseif (is_page()) {
    echo '<p>這是頁面。</p>';
} else {
    echo '<p>這是其他類型頁面。</p>';
}

比較運算與嚴格比較

PHP 有寬鬆比較 == 與嚴格比較 ===。WordPress 開發中建議優先使用嚴格比較,因為它會同時比較值與型別,較不容易出現意外結果。

$status = '0';

if ($status === 0) {
    echo '這段不會執行,因為型別不同';
}

if ($status === '0') {
    echo '這段會執行';
}

switch 與多狀態顯示

當同一個變數有多種狀態時,switch 會比多層 if 更清楚。例如依課程難度輸出標籤:

switch ($level) {
    case 'beginner':
        $label = '基礎';
        break;
    case 'intermediate':
        $label = '進階';
        break;
    default:
        $label = '高階';
}

5.4 迴圈指令

迴圈用於處理多筆資料。WordPress 最經典的迴圈是 The Loop,用來逐篇輸出查詢到的文章。

if (have_posts()) {
    while (have_posts()) {
        the_post();
        the_title('<h2>', '</h2>');
        the_excerpt();
    }
}

foreach 處理陣列

$features = ['安全性', '效能', '可維護性'];
foreach ($features as $feature) {
    echo '<li>' . esc_html($feature) . '</li>';
}

自訂查詢後重置資料

如果你使用 WP_Query 建立額外查詢,迴圈結束後要呼叫 wp_reset_postdata(),讓全域文章資料回到原本主查詢。這是 WordPress 主題開發中很常見、也很容易忘記的步驟。

$query = new WP_Query(['posts_per_page' => 3]);

while ($query->have_posts()) {
    $query->the_post();
    the_title('<h3>', '</h3>');
}

wp_reset_postdata();

5.5 函式的運用

函式能把重複邏輯集中管理。WordPress 的 hook 也常需要把自訂函式交給 add_action()add_filter()

function wp2026_format_label($text) {
    return '[' . trim($text) . ']';
}

add_filter('the_title', 'wp2026_format_label');

撰寫函式時,名稱要避免與 WordPress 核心或其他外掛衝突,實務上常加上專案前綴,例如 wp2026_

函式參數與回傳值

好的函式應該有清楚的輸入與輸出。以下函式接收課程資料陣列,回傳已轉義的 HTML 字串:

function wp2026_render_course_title(array $course): string {
    $title = $course['title'] ?? '未命名課程';
    return '<h3>' . esc_html($title) . '</h3>';
}

若函式會直接輸出畫面,可以在名稱中使用 renderdisplay 等字;若只是取得資料,可使用 get,讓呼叫端更容易理解用途。

Hook callback 的寫法

add_action()add_filter() 註冊的函式稱為 callback。Filter callback 通常要接收原始值,修改後回傳;Action callback 則多半執行某個動作。

add_filter('excerpt_length', 'wp2026_excerpt_length');
function wp2026_excerpt_length($length) {
    return 80;
}

5.6 GitHub Copilot 的安裝與使用

Copilot 可協助補全程式、產生範例與解釋錯誤,但它不理解你的完整專案責任。使用時應先寫清楚註解與函式名稱,再檢查輸出是否符合 WordPress Coding Standards、安全轉義與權限檢查。

適合交給 Copilot 的任務

  • 產生重複性高的陣列或設定範例。
  • 補齊函式註解與簡單測試資料。
  • 根據既有程式風格建立類似函式。
  • 解釋 PHP 錯誤訊息可能代表的原因。

使用 AI 後的人工檢查

Copilot 產生的程式碼務必檢查四件事:是否有權限檢查、是否有 nonce、輸入是否清理、輸出是否轉義。若是資料庫查詢,也要確認是否使用 WordPress API 或 prepared statement。

// 請 Copilot 產生後,仍要自己確認:
// 1. current_user_can()
// 2. check_admin_referer()
// 3. sanitize_*()
// 4. esc_*()

本章練習

  1. 建立一個 PHP 陣列儲存三個課程資料。
  2. foreach 輸出課程清單。
  3. 寫一個函式,把課程標題包成 HTML 標題。
  4. 請 Copilot 產生範例後,手動檢查是否有轉義輸出。