函數可用以下語法來定義
<?php
function foo($arg_1, $arg_2, /* ..., */ $arg_n)
{
echo "Example function.\n";
return $retval;
}
?>
函數不需要在使用之前被定義,除非是函數是有條件被定義時,才必須在使用前定義
舉以下範例
<?php
$makefoo = true;
/* 不能在此處調用foo()函數,
因為它還不存在,但可以調用bar()函數。*/
bar();
if ($makefoo) {
function foo()
{
echo "I don't exist until program execution reaches me.\n";
}
}
/* 現在可以安全調用函數 foo()
因為 $makefoo 值為真true */
if ($makefoo) foo();
function bar()
{
echo "I exist immediately upon program start.\n";
}
?>
<?php
function foo()
{
function bar()
{
echo "I don't exist until foo() is called.\n";
}
}
/* 現在還不能調用 bar() 函數,因為它還不存在 */
foo();
/* 現在可以調用 bar() 函數了,因為 foo() 函數的執行使得 bar() 函數變為已定義的函數 */
bar();
?>
PHP 中的所有函數和類都具有全局作用域,可以定義在一個函數之內而在之外調用,反之亦然。
PHP 不支持函數重載,也不可能取消定義或者重定義已聲明的函數。
還有遞迴函數,也就是自己呼叫自己
舉個費氏數列的例子(從0,1開始,後面的數是前兩個數相加)
<?php
function fib($n)
{
if($n == 0) return 0;
if($n == 1) return 1;
return fib($n-1) + fib($n - 2);
}
for($i = 0; $i <= 5; $i++){
echo fib("$i ");
}
// outputs
// 0,1,1,2,3,5
注意: 但是要避免遞歸函數/方法調用超過 100-200 層,因為可能會使堆積崩潰從而使當前腳本終止。無限遞歸可視為編程錯誤
通過給予函數參數,傳遞訊息給函數,可以放入多個參數用逗號分隔,也可以設置參數默認的值。
<?php
function takes_array($nums)
{
echo '$nums[0] + $nums[1] = ', $nums[0] + $nums[1];
}
從php8開始參數尾巴逗號是會被忽略的
<?php
function takes_many_args(
$first_name,
$last_name,
$age,
$gender = 1,
$cellphone = null, // 在 8.0.0 之前,尾部逗號是不允许的。
)
{
// ...
}
?>
從 PHP 8.0.0 開始,不推薦在可選參數之後傳遞強制參數。 這通常可以通過刪除默認值來解決。 此規則的一個例外是 Type $param = null 形式的參數,其中 null 默認值使類型隱式可為空。 這種用法仍然被允許,但建議改用顯式可為空類型。
<?php
function foo($a = [], $b) {} // 之前
function foo($a, $b) {} // 之後
function bar(A $a = null, $b) {} // 同時可用
function bar(?A $a, $b) {} // 官方推薦
?>
PHP 還允許使用數組 array 和特殊類型 null 作為默認參數。
<?php
function makecoffee($type = "cappuccino")
{
return "Making a cup of $type.\n";
}
echo makecoffee();
echo makecoffee(null);
echo makecoffee("espresso");
?>
// outputs
// Making a cup of cappuccino.
// Making a cup of .
// Making a cup of espresso.
默認值必須是常量表達式,不能是,如變量,類成員,或者函數調用等。 注意當使用默認參數時,任何默認參數必須放在任何非默認參數的右側;否則,函數將不會按照預期的情況工作。
<?php
function makeyogurt($type = "acidophilus", $flavour)
{
return "Making a bowl of $type $flavour.\n";
}
echo makeyogurt("raspberry"); // won't work as expected
?>
// Warning: Missing argument 2 in call to makeyogurt()
<?php
function makeyogurt($flavour, $type = "acidophilus")
{
return "Making a bowl of $type $flavour.\n";
}
echo makeyogurt("raspberry"); // works as expected
?>
// outputs
// Making a bowl of acidophilus raspberry.
PHP 在用戶自定義函數中支持可變數量的參數列表。由 ... 語法實現。
包含 ... 的參數,會轉換為指定參數變量的一個數組(類似字典),以下示例:
<?php
function sum(...$numbers) {
$acc = 0;
foreach ($numbers as $n) {
$acc += $n;
}
return $acc;
}
echo sum(1, 2, 3, 4);
?>
// 10
<?php
function add($a, $b) {
return $a + $b;
}
echo add(...[1, 2])."\n";
$a = [1, 2];
echo add(...$a);
?>
// 3
// 3
<?php
function total_intervals($unit, DateInterval ...$intervals) { // 必須傳遞DateInterval類的參數
$time = 0;
foreach ($intervals as $interval) {
$time += $interval->$unit;
}
return $time;
}
$a = new DateInterval('P1D');
$b = new DateInterval('P2D');
echo total_intervals('d', $a, $b).' days';
// This will fail, since null isn't a DateInterval object.
echo total_intervals('d', null);
?>
// outputs
// 3 days
// Catchable fatal error: Argument 2 passed to total_intervals() must be an instance of DateInterval,
// null given, called in - on line 14 and defined in - on line 2
PHP 8.0.0 開始引入了命名參數作為現有位置參數的擴展。命名參數允許根據參數名而不是參數位置向函數傳參。這使得參數的含義自成體系,參數與順序無關,並允許任意跳過默認值。
命名參數通過在參數名前加上冒號來傳遞。允許使用保留關鍵字作為參數名。參數名必須是一個標識符,不允許動態指定。
<?php
function myFunction($paramName){
echo $paramName;
}
myFunction(paramName: $value); // $value指定給予paramName這個參數
array_foobar(array: $value);
// NOT supported.
function_name($variableStoringParamName: $value); // 不能動態指定
?>
<?php
// 使用順序傳遞:
array_fill(0, 100, 50);
// 使用命名參數:
array_fill(start_index: 0, count: 100, value: 50);
?>
順序不重要,下面輸出跟上面一樣
<?php
array_fill(value: 50, count: 100, start_index: 0);
?>
<?php
function foo($param) { ... }
foo(param: 1, param: 2);
// Error: Named parameter $param overwrites previous argument
foo(1, param: 2);
// Error: Named parameter $param overwrites previous argument
?>
資料來源: https://www.php.net/