資深 PHP 工程師技術面試題庫與深入解析
作為一名資深 PHP 工程師,面試不僅考驗基礎知識,還需展現對語言深度、架構設計、效能優化、安全性以及實務工具的掌握。本文將提供的面試題庫擴展為一篇技術文章,分為五大類別。每個問題不僅列出,還附上深入解析、程式碼範例與實務應用建議,幫助面試官評估候選人,也讓求職者更好地準備。這些題目聚焦於挑戰性與辨識度,涵蓋 PHP 生態系的核心元素,如 Laravel 框架。
一、語言與語法理解
PHP 作為一門動態語言,其語法與內建機制是工程師的基礎。這類題目旨在檢視候選人對語言細節的掌握,避免常見陷阱。
1. PHP 中 __construct()
、__destruct()
、__invoke()
的用途與差異?
解析:
__construct()
:類別建構子,用於初始化物件。當使用new
關鍵字建立物件時自動呼叫,可接受參數進行設定。例如,在 Laravel 的控制器中常用來注入依賴。__destruct()
:類別解構子,用於釋放資源,如關閉資料庫連線。當物件被銷毀(如腳本結束或 unset)時自動呼叫。實務上,用於清理檔案句柄或快取。__invoke()
:讓物件像函數一樣被呼叫。當物件被當作函數使用時觸發,例如$obj()
。這在閉包或可呼叫物件中常見,適合用於回呼或事件處理。
差異:建構與解構聚焦生命週期管理,invoke 則提供函數式程式設計的彈性。誤用可能導致資源洩漏或意外行為。
範例程式碼:
class Example {
public function __construct() {
echo "Object created\n";
}
public function __destruct() {
echo "Object destroyed\n";
}
public function __invoke($arg) {
echo "Invoked with $arg\n";
}
}
$obj = new Example(); // 輸出: Object created
$obj('test'); // 輸出: Invoked with test
unset($obj); // 輸出: Object destroyed
2. 請說明 PHP 中的 Trait
是什麼?與繼承有何不同?
解析:
Trait
是 PHP 5.4 引入的水平繼承機制,允許在多個類別中重用方法,而不需建立階層結構。適合橫跨類別的共享行為,如記錄功能。- 與繼承不同:繼承是垂直的(單一或多重,但 PHP 只支援單繼承),可能導致鑽石問題;Trait 則可多重使用,方法衝突時可透過
insteadof
或as
解決。Trait 不支援屬性繼承,但可定義抽象方法強制實作。
實務應用:在 Laravel 中,常用 Trait 如 SoftDeletes
來添加軟刪除功能,而非修改基類。
範例程式碼:
trait Loggable {
public function log($message) {
echo "Logged: $message\n";
}
}
class User {
use Loggable;
}
$user = new User();
$user->log('User created'); // 輸出: Logged: User created
3. isset()
與 empty()
的差異是什麼?在什麼情境下會誤用?
解析:
isset()
:檢查變數是否存在且不為 null,返回 true 即使值為 0 或空字串。empty()
:檢查變數是否為「空值」,包括 0、''、false、[]、null 等。等同於!isset($var) || $var == false
。
差異與誤用:empty()
可能誤判 0 為空(如年齡欄位),導致邏輯錯誤。情境:表單驗證時,isset($_POST['field'])
檢查是否存在,empty()
檢查是否有值。
範例:
$var = 0;
var_dump(isset($var)); // bool(true)
var_dump(empty($var)); // bool(true) // 誤判為空
4. PHP 中的型別提示(Type Hinting)與型別宣告(Type Declaration)有何不同?
解析:
- 型別提示(Type Hinting):PHP 5 引入,用於參數與返回值,強制類型檢查。如
function foo(array $arr)
。 - 型別宣告(Type Declaration):PHP 7 強化版,支援 scalar types(如 int、string),並可設為 strict mode (
declare(strict_types=1);
) 強制轉型失敗拋異常。
差異:宣告更嚴格,支援可空型別(如 ?int)。實務:API 開發中確保輸入一致性。
範例:
declare(strict_types=1);
function add(int $a, int $b): int {
return $a + $b;
}
echo add(1, 2); // 3
// add('1', 2); // TypeError
5. 請解釋 Generator
的運作原理與使用場景。
解析:
- Generator 使用
yield
關鍵字暫停/恢復執行,產生迭代器而不一次性載入所有資料。內部基於協程,記憶體高效。 - 原理:呼叫 Generator 函數返回 Generator 物件,foreach 迭代時逐步 yield 值。
場景:處理大檔或無限序列,如讀取大型 CSV 檔,避免記憶體爆滿。
範例:
function genNumbers($start, $end) {
for ($i = $start; $i <= $end; $i++) {
yield $i;
}
}
foreach (genNumbers(1, 1000000) as $num) {
// 逐步處理,不載入全部
}
二、架構設計與模式應用
這類題目評估候選人對軟體設計原則的應用,特別在大型 PHP 專案中。
1. 請說明 MVC 與 Layered Architecture 的差異,並舉例何時選用哪一種。
解析:
- MVC(Model-View-Controller):分離關注點,Model 處理資料,View 呈現,Controller 協調。適合 Web 應用,如 Laravel。
- Layered Architecture:多層結構(如 Presentation、Business、Data Access),層間單向依賴,易測試與維護。
差異:MVC 更聚焦 UI 互動,Layered 更通用於企業應用。選用:小型 Web App 用 MVC;複雜系統(如 ERP)用 Layered 以分層隔離。
2. 如何在 Laravel 中實作 Repository + Service Layer?請簡述其優點。
解析:
- Repository:抽象資料存取,介面定義方法,實作處理 Eloquent 或其他 ORM。
- Service Layer:業務邏輯層,注入 Repository,處理複雜操作。
優點:解耦資料層,便於切換資料源、單元測試;提升可維護性。
範例:
// UserRepositoryInterface.php
interface UserRepositoryInterface {
public function findById($id);
}
// UserRepository.php
class UserRepository implements UserRepositoryInterface {
public function findById($id) {
return User::find($id);
}
}
// UserService.php
class UserService {
protected $userRepo;
public function __construct(UserRepositoryInterface $userRepo) {
$this->userRepo = $userRepo;
}
public function getUser($id) {
return $this->userRepo->findById($id);
}
}
3. 請舉例說明 Dependency Injection 在 Laravel 中的實際應用。
解析:
- DI:透過建構子或方法注入依賴,而非硬編碼。Laravel 的 IoC 容器自動解析。
應用:控制器注入服務,易嘲弄測試。
範例:
class UserController extends Controller {
protected $userService;
public function __construct(UserService $userService) {
$this->userService = $userService;
}
public function show($id) {
return $this->userService->getUser($id);
}
}
4. 請說明 Event-Driven 設計在 PHP 專案中的應用場景。
解析:
- 事件驅動:發佈事件,監聽器回應。Laravel 使用 Events 和 Listeners。
場景:使用者註冊後發送郵件、更新快取;解耦模組,如微服務間通訊。
範例:
// EventServiceProvider.php
protected $listen = [
UserRegistered::class => [SendWelcomeEmail::class],
];
5. 如何設計一個可擴充的 Plugin 系統?請簡述架構與關鍵考量。
解析:
- 架構:使用 Hook(如事件)、介面契約;插件註冊自身事件或服務。
- 考量:版本相容、安全性(沙盒執行)、效能(避免過多 Hook)。
實務:WordPress 式 Hook 或 Laravel 的 Package 開發。
三、效能與安全性
效能與安全是資深工程師的核心技能,這類題目聚焦實戰優化。
1. 如何優化 Laravel 專案的查詢效能?請列出三種方法。
解析:
- Eager Loading:使用
with()
避免 N+1 問題。 - Indexing:資料庫加索引於頻繁查詢欄位。
- Caching:快取查詢結果,如 Redis。
範例:
$users = User::with('posts')->get(); // Eager Loading
2. 請說明 SQL Injection 的原理與防範方式。
解析:
- 原理:攻擊者注入惡意 SQL 至查詢字串,執行未預期命令。
- 防範:使用 Prepared Statements、PDO 綁定參數。
範例:
$stmt = $pdo->prepare('SELECT * FROM users WHERE id = :id');
$stmt->execute(['id' => $userId]);
3. 如何在 PHP 中處理大量資料的匯入與記憶體管理?
解析:
- 使用 Generator 逐行讀取;分批處理(如 chunk);監控 memory_get_usage()。
範例:CSV 匯入使用 fgetcsv 迴圈。
4. 請說明 CSRF 的攻擊方式與 Laravel 的防禦機制。
解析:
- 攻擊:偽造請求,利用登入狀態執行操作。
- 防禦:Laravel 使用 CSRF Token,中間件驗證。
範例:
<form method="POST" action="/profile">
@csrf
</form>
5. 如何使用 Laravel 的 Cache 機制提升效能?請舉例。
解析:
- Cache::remember() 快取計算結果,支持 driver 如 file、redis。
範例:
$users = Cache::remember('users', 60, function () {
return User::all();
});
四、工具與實務經驗
評估候選人對 DevOps 與測試的熟悉度。
1. 請說明如何使用 Docker 建立 PHP 開發環境,並處理 Laravel 的 queue。
解析:
- Dockerfile:基於 php:apache,安裝 Composer、PDO。
- docker-compose:定義服務,如 php、mysql、redis (for queue)。
- Queue:使用 supervisor 運行 worker。
範例 docker-compose.yml:
services:
app:
image: php:8.1-apache
volumes: ['./:/var/www/html']
queue:
image: php:8.1-cli
command: php artisan queue:work
2. 如何設計 CI/CD 流程以自動部署 Laravel 專案?
解析:
- 使用 GitHub Actions 或 GitLab CI:測試、建置、部署。
- 步驟:Composer install、PHPUnit、部署至 server (如 Forge)。
3. 請說明 Composer 的 autoload 機制與 PSR-4 的關係。
解析:
- Autoload:透過 composer.json 的 autoload 註冊類別載入。
- PSR-4:命名空間對應目錄結構,自動載入類別。
範例 composer.json:
"autoload": {
"psr-4": {
"App\\": "app/"
}
}
4. 如何使用 PHPUnit 撰寫 Laravel 的整合測試?
解析:
- 使用 TestCase,模擬請求,斷言回應。
範例:
class ExampleTest extends TestCase {
public function testBasicTest() {
$response = $this->get('/');
$response->assertStatus(200);
}
}
5. 請說明 Laravel 的 Job 與 Queue 的運作流程與實務應用。
解析:
- Job:封裝任務,dispatch 至 queue。
- 流程:dispatch -> queue driver (redis) -> worker 執行。
應用:背景郵件發送、報告生成。
五、系統設計與實戰挑戰題
這些開放題檢視問題解決能力。
1. 假設你要設計一個預約系統,如何處理高併發與時段衝突?
解析:
- 使用樂觀鎖定(versioning)或悲觀鎖定(DB lock)。
- Redis 鎖定時段;分佈式鎖如 Redlock。
2. 如何設計一個推薦系統,根據使用者行為提供動態建議?
解析:
- 收集行為資料,ML 模型(如 collaborative filtering)。
- Laravel:Job 計算相似度,Cache 結果。
3. 請設計一個 API,支援版本控制、授權、速率限制,並說明架構。
解析:
- 版本:URI 如 /v1/users;授權:JWT;限速:Middleware。
- 架構:RESTful,Dingo API 套件。
4. 如何設計一個模組化的 Laravel 專案,支援多租戶(multi-tenant)架構?
解析:
- 單一 DB 多 schema,或多 DB。
- Middleware 切換 tenant;Package 分離模組。
5. 請分享你曾經處理過最困難的技術挑戰,以及你的解決策略。
解析:
- 開放討論,聚焦 debug、優化或架構重構經驗。
總結
這份題庫與解析涵蓋 PHP 資深工程師的核心技能,強調深度理解與實務應用。面試時,可根據候選人回應追問細節,以評估其經驗。求職者則可透過範例練習,提升競爭力。
沒有留言:
張貼留言