🧠 PHP 函數從入門到精通
PHP 函數是編程中最基礎、也是最強大的工具之一。它不僅可以簡化代碼、提高復用性,還能通過各種高級用法,讓你寫出更靈活、更現代的代碼。
下面我們從函數的基礎講起,逐步深入,帶你掌握函數的核心用法和高級技巧,即使是編程小白也能輕松理解!
🧩 一、函數基礎:定義與調用
函數是將一段代碼封裝起來,方便重復使用的代碼塊。
function greet($name) {echo "Hello, $name";
}greet("Tom"); // 輸出:Hello, Tom
function
是定義函數的關鍵字$name
是參數greet("Tom")
是調用函數
📦 二、傳參方式:值傳參 vs 引用傳參
1?? 值傳參(默認)
function add($a) {$a++;
}$a = 1;
add($a);
echo $a; // 輸出:1
函數內部操作的是變量的副本,不會影響原始變量。
2?? 引用傳參(使用 &
)
function add(&$a) {$a++;
}$a = 1;
add($a);
echo $a; // 輸出:2
&$a
表示傳入的是變量的引用,函數內部對變量的修改會影響外部。
🎁 三、默認參數:讓函數更靈活
你可以為函數參數設置默認值,這樣在調用時可以省略這些參數。
function greet($name = "Guest") {echo "Hello, $name";
}greet(); // 輸出:Hello, Guest
greet("Tom"); // 輸出:Hello, Tom
? 支持類型:
- 標量類型(
int
,string
,bool
,float
) array
null
- 從 PHP 8.1 開始支持對象
class User {public function __construct(public string $name = "Guest") {}
}function greet(User $user = new User()) {echo "Hello, " . $user->name;
}greet(); // 輸出:Hello, Guest
🧩 四、命名參數(PHP 8.0+)
命名參數允許你按參數名傳參,跳過中間的可選參數。
function makeYogurt($container = "bowl",$flavour = "raspberry",$style = "Greek"
) {return "Making a $container of $flavour $style yogurt.\n";
}echo makeYogurt(style: "natural");
// 輸出:Making a bowl of raspberry natural yogurt.
? 更清晰、更靈活,推薦使用。
🧮 五、可變參數(Variadic Parameters)
當函數需要接收不確定數量的參數時,可以使用可變參數語法 ...$params
。
function sum(...$nums) {return array_sum($nums);
}echo sum(1, 2, 3, 4); // 輸出:10
...$nums
會把所有傳入的參數收集成一個數組。- 你還可以用它來“展開”數組傳參:
$values = [1, 2, 3];
echo sum(...$values); // 輸出:6
? 可變參數與正常參數結合使用
可變參數必須是函數參數列表中的最后一個參數,前面可以有正常參數。
function logMessage($level, ...$messages) {echo "[$level] ";foreach ($messages as $msg) {echo "$msg ";}echo "\n";
}logMessage("INFO", "User", "logged", "in");
// 輸出:[INFO] User logged in
🔄 六、可變函數(動態調用函數)
你可以將函數名保存在變量中,并動態調用它。
function add($a, $b) {return $a + $b;
}$func = "add";
echo $func(1, 2); // 輸出:3
? 常用于回調、插件系統等場景。
🧩 七、實戰示例:結合命名參數 + 可變參數 + 可變函數
下面是一個非常實用的綜合示例,展示了三者如何結合使用:
function formatData(string $type = "json", bool $pretty = false, ...$data) {if ($pretty) {print_r($data);} else {echo json_encode($data);}
}
? 使用可變函數調用 + 命名參數
$formatter = 'formatData';// 使用命名參數 + 可變參數調用
$formatter(type: "json",pretty: true,"name", "age", "email"
);
📌 輸出結果:
Array
([0] => name[1] => age[2] => email
)
😶?🌫? 八、匿名函數(閉包)
匿名函數是沒有名字的函數,通常用于作為參數傳遞給其他函數,或者作為返回值。
$add = function($a, $b) {return $a + $b;
};echo $add(1, 2); // 輸出:3
你還可以在閉包中使用外部變量,只需要加上 use
:
$prefix = "結果是:";
$add = function($a, $b) use ($prefix) {return $prefix . ($a + $b);
};echo $add(2, 3); // 輸出:結果是:5
?
use
可以讓閉包訪問它外部的變量。
🔗 bindTo:綁定閉包的上下文
有時候你想讓閉包訪問類的私有屬性或方法,可以使用 bindTo()
:
class User {private $name = "Alice";
}$getName = function() {return $this->name;
};$user = new User();
$bound = $getName->bindTo($user, 'User');echo $bound(); // 輸出:Alice
- 第一個參數是綁定的對象(
$this
) - 第二個參數是類名,表示閉包可以訪問這個類的私有成員
🔄 Closure::fromCallable:將方法轉為閉包
你可以把一個類的方法轉換成閉包對象,這樣就能像函數一樣使用它:
class Greeter {private function sayHello($name) {return "Hello, $name";}
}$greeter = new Greeter();
$hello = Closure::fromCallable([$greeter, 'sayHello']);echo $hello("Tom"); // 輸出:Hello, Tom
?? 九、箭頭函數(PHP 7.4+)
箭頭函數是匿名函數的簡化版,寫法更簡潔,自動繼承外部變量。
$add = fn($a, $b) => $a + $b;echo $add(1, 2); // 輸出:3
它有幾個特點:
- ? 自動繼承外部變量(不需要寫
use
) - ? 對外部變量只有讀權限(不能修改)
- ? 只能寫一行表達式(不能寫多行邏輯)
🔖 十、First-class Callable(PHP 8.1+)
PHP 8.1 引入了一種新的方式,可以更方便地引用函數或方法:
$fn = strlen(...); // 獲取 strlen 函數的引用
echo $fn("hello"); // 輸出:5
-
...
是語法的一部分,表示你不是在調用函數,而是在引用它。 -
這種方式可以引用:
- 普通函數:
strlen(...)
- 靜態方法:
Math::add(...)
- 實例方法:
$greeter->sayHello(...)
- 普通函數:
它返回的是一個 Closure
,可以像閉包一樣調用。