閉包 是 PHP 5.3+ 引入的強大特性,允許函數捕獲並保存定義時的上下文變量。本文通過 Laravel 控制器實例,演示如何在閉包中使用 use 引入外部變量,並結合參數傳遞實現靈活的回調模式。
use 關鍵字:將父作用域變量「導入」閉包內部,默認按值捕獲,加 & 可按引用捕獲假設我們需要一個通用的 execClosure() 方法執行各種閉包,並記錄執行名稱:
class TestController extends Controller {
/** 測試閉包傳參與 use 引用外部變量 */
public function testClosure($t1, $t2) {
// 定義閉包:接收兩個參數,use 引入控制器方法參數 $t1、$t2
$closure = function ($param1, $param2) use ($t1, $t2) {
echo $param1 . $param2 . $t1 . $t2;
};
// 傳遞閉包給執行器
$this->execClosure('test.closure', $closure);
}
/** 通用閉包執行器 */
protected function execClosure($name, Closure $closure) {
echo 'Closure func name: ' . $name . '<br>';
// 調用閉包並傳入參數
$closure('p1', 'p2');
}
}
// routes.php
Route::get('/test/closure/{t1}/{t2}', ['uses' => 'TestController@testClosure']);
訪問 https://example.com/test/closure/hehe1/hehe2
Closure func name:test.closure p1p2hehe1hehe2
執行流程:
t1=hehe1、t2=hehe2 傳入 testClosure()use ($t1, $t2) 捕獲這兩個值(按值捕獲,快照機制)execClosure() 接收閉包,先輸出名稱$closure('p1', 'p2'),閉包內部拼接:p1 + p2 + hehe1 + hehe2| 寫法 | 行為 | 適用場景 |
|---|---|---|
use ($var) | 按值捕獲(複製),閉包內修改不影響外部 | 只讀外部配置、常量 |
use (&$var) | 按引用捕獲,閉包內修改同步到外部 | 累加器、狀態修改、延遲綁定 |
use ($a, &$b) | 混合模式 | 複雜邏輯需區分只讀/可寫 |
$counter = 0;
$increment = function () use (&$counter) {
return ++$counter;
};
echo $increment(); // 1
echo $increment(); // 2
echo $increment(); // 3
// $counter 現在為 3
Route::get('/', function () use ($config) { ... })User::where(function ($q) use ($keyword) { $q->where('name', 'like', "%$keyword%"); })dispatch(function () use ($orderId) { ProcessOrder::handle($orderId); })$collection->map(function ($item) use ($exchangeRate) { return $item->price * $exchangeRate; })foreach ($items as $item) { $funcs[] = function () use ($item) { ... }; } — 所有閉包捕獲的是同一個 $item 變量的最終值,解決方法:use ($item) 改為 use ($item) 並在循環體內 $captured = $item; use ($captured)use 僅支持變量,不支持 use ($this->property) 這種表達式,需先賦值給變量Closure::fromCallable() 將類方法轉為閉包,更優雅掌握 use 機制是寫好 PHP 函數式代碼的關鍵。記住:按值捕獲是快照,按引用捕獲是鏈接。結合類型提示 Closure $closure,能構建出類型安全、高度解耦的回調系統。