函數(shù)是指可重復(fù)使用的程序片段。它們?cè)试S你為某個(gè)代碼塊賦予名字泻骤,允許你通過(guò)這一特殊的名字在你的程序任何地方來(lái)運(yùn)行代碼塊漆羔,并可重復(fù)任何次數(shù)。這就是所謂的調(diào)用函數(shù)狱掂。我們已經(jīng)使用過(guò)了許多內(nèi)置函數(shù)演痒,例如:strlen
和 trim
。
函數(shù)概念可能是在任何復(fù)雜的軟件(無(wú)論使用的是何種編程語(yǔ)言)中最重要的部分趋惨,所以我們接下來(lái)將在本章中探討有關(guān)函數(shù)的各個(gè)方面鸟顺。
函數(shù)可以通過(guò)關(guān)鍵字 function
來(lái)定義。這一關(guān)鍵字后跟一個(gè)函數(shù)的標(biāo)識(shí)符名稱器虾,在跟一對(duì)圓括號(hào)讯嫂,其中可以包括一些變量的名稱,隨后而來(lái)的是包含在大括號(hào)中語(yǔ)句塊兆沙。下面的示例將會(huì)展示出這其實(shí)非常簡(jiǎn)單:
示例(保存為 function1.php
):
<?php
function say_hello() {
// 該塊屬于這一函數(shù)
echo 'hello world' . "\n";
}
say_hello(); // 調(diào)用函數(shù)
say_hello(); // 再次調(diào)用函數(shù)
輸出:
$ php function1.php
hello world
hello world
它是如何工作的
我們以上文解釋過(guò)的方式定義名為 say_hello
的函數(shù)欧芽。這個(gè)函數(shù)不使用參數(shù),因此在括號(hào)中沒(méi)有聲明變量葛圃。函數(shù)的參數(shù)只能輸入到函數(shù)中千扔,以便可以傳遞不同的值給它,并獲得相應(yīng)的結(jié)果库正。
可以注意到我們能夠兩次調(diào)用相同的函數(shù)曲楚,這意味著我們不需要把代碼再重新寫(xiě)一遍。
函數(shù)的參數(shù)
通過(guò)參數(shù)列表可以傳遞信息到函數(shù)褥符,即以逗號(hào)作為分隔符的表達(dá)式列表龙誊。參數(shù)是從左向右求值的。要注意在此使用的術(shù)語(yǔ)——在定義函數(shù)時(shí)給定的名稱稱作“形參”(Parameters)喷楣,在調(diào)用函數(shù)時(shí)你所提供給函數(shù)的值稱作“實(shí)參”(Arguments)趟大。
示例(保存為 function_param.php
):
<?php
function print_max($a, $b) {
if ($a > $b) {
echo $a . ' is maximum' . "\n";
} elseif ($a == $b) {
echo $a . ' is equal to ' . $b . "\n";
} else {
echo $b . ' is maximum' . "\n";
}
}
// 直接傳遞字面值
print_max(3, 4);
$x = 5;
$y = 7;
// 以參數(shù)的形式傳遞變量
print_max($x, $y);
輸出:
$ php function_param.php
4 is maximum
7 is maximum
它是如何工作的
在這里鹤树,我們將函數(shù)命名為 print_max
并使用兩個(gè)參數(shù)分別稱作 $a
和 $b
。我們使用一個(gè)簡(jiǎn)單的 if...else
語(yǔ)句來(lái)找出更大的那個(gè)數(shù)护昧,并將它打印出來(lái)魂迄。
第一次調(diào)用函數(shù) print_max
時(shí),我們以實(shí)參的形式直接向函數(shù)提供這一數(shù)字惋耙。在第二次調(diào)用時(shí)捣炬,我們將變量作為實(shí)參來(lái)調(diào)用函數(shù)。print_max(x, y)
將使得實(shí)參 $x
的值將被賦值給形參 $a
绽榛,而實(shí)參 $y
的值將被賦值給形參 $b
湿酸。在兩次調(diào)用中,print_max
都以相同的方式工作灭美。
局部變量
當(dāng)你在一個(gè)函數(shù)的定義中聲明變量時(shí)推溃,它們不會(huì)以任何方式與身處函數(shù)之外但具有相同名稱的變量產(chǎn)生關(guān)系,也就是說(shuō)届腐,這些變量名只存在于函數(shù)這一局部(Local)铁坎。這被稱為變量的作用域(Scope)。所有變量的作用域是它們被定義的塊犁苏,從定義它們的名字的定義點(diǎn)開(kāi)始硬萍。
示例(保存為 function_local.php
):
<?php
$x = 50;
function func($x) {
echo '$x is ' . $x . "\n";
$x = 2;
echo 'Changed local $x to ' . $x . "\n";
}
func($x);
echo '$x is still ' . $x . "\n";
輸出:
$ php function_local.php
$x is 50
Changed local $x to 2
$x is still 50
它是如何工作的
當(dāng)我們第一次打印出存在于函數(shù)塊的第一行的名為 $x
的值時(shí),PHP 使用的是在函數(shù)聲明之上的主代碼塊中聲明的這一參數(shù)的值围详。
接著朴乖,我們將值 2
賦值給 $x
。$x
是我們這一函數(shù)的局部變量助赞。因此买羞,當(dāng)我們改變函數(shù)中 $x
的值的時(shí)候,主代碼塊中的 $x
則不會(huì)受到影響雹食。
隨著最后一句 echo
語(yǔ)句骗灶,我們展示出主代碼塊中定義的 $x
的值掸屡,由此確認(rèn)它實(shí)際上不受先前調(diào)用的函數(shù)中的局部變量的影響抢埋。
global
語(yǔ)句
如果你想給一個(gè)在程序頂層的變量賦值(也就是說(shuō)它不存在于任何作用域中票顾,無(wú)論是函數(shù)還是類)凌埂,那么你必須告訴 PHP 這一變量并非局部的卒落,而是全局(Global)的瓣颅。我們可以通過(guò) global
語(yǔ)句來(lái)完成這件事弧岳。
示例(保存為 function_global.php
):
<?php
$x = 50;
function func($x) {
global $x;
echo '$x is ' . $x . "\n";
$x = 2;
echo 'Changed global $x to ' . $x . "\n";
}
func($x);
echo 'Value of $x is ' . $x . "\n";
輸出:
$ php function_global.php
$x is 50
Changed global $x to 2
Value of $x is 2
它是如何工作的
global
語(yǔ)句用以聲明 $x
是一個(gè)全局變量——因此化撕,當(dāng)我們?cè)诤瘮?shù)中為 $x
進(jìn)行賦值時(shí)几晤,這一改動(dòng)將影響到我們?cè)谥鞔a塊中使用的 $x
的值。
你可以在同一句 global
語(yǔ)句中指定不止一個(gè)的全局變量植阴,例如 global $x, $y, $z;
蟹瘾。
通過(guò)引用傳遞參數(shù)
默認(rèn)情況下圾浅,函數(shù)參數(shù)通過(guò)值傳遞(因而即使在函數(shù)內(nèi)部改變參數(shù)的值,它并不會(huì)改變函數(shù)外部的值)憾朴。如果希望允許函數(shù)修改它的參數(shù)值狸捕,必須通過(guò)引用傳遞參數(shù)。
如果想要函數(shù)的一個(gè)參數(shù)總是通過(guò)引用傳遞众雷,可以在函數(shù)定義中該參數(shù)的前面加上符號(hào) &
:
示例(保存為 function_update.php
):
<?php
function add_some_extra(&$string)
{
$string .= 'and something extra.';
}
$str = 'This is a string, ';
add_some_extra($str);
echo $str;
輸出:
$ php function_update.php
This is a string, and something extra.
它是如何工作的
通過(guò)在參數(shù) $string
前加上符號(hào) &
灸拍,按照引用進(jìn)行傳值,從而允許函數(shù)修改它的參數(shù)值砾省。
默認(rèn)參數(shù)值
對(duì)于一些函數(shù)來(lái)說(shuō)鸡岗,你可能為希望使一些參數(shù)(可選)并使用默認(rèn)的值,以避免用戶不想為他們提供值的情況编兄。默認(rèn)參數(shù)值可以有效幫助解決這一情況轩性。你可以通過(guò)在函數(shù)定義時(shí)附加一個(gè)賦值運(yùn)算符(=
)來(lái)為參數(shù)指定默認(rèn)參數(shù)值。
默認(rèn)值必須是常量表達(dá)式狠鸳,不能是諸如變量揣苏,類成員,或者函數(shù)調(diào)用等件舵。
示例(保存為 function_default.php
):
<?php
function say($message, $times = 1) {
for ($i = 0; $i < $times; $i++) {
echo $message;
}
echo "\n";
}
say('Hello');
say('World', 5);
輸出:
$ php function_default.php
Hello
WorldWorldWorldWorldWorld
它是如何工作的
名為 say
的函數(shù)用以按照給定的次數(shù)打印一串字符串卸察。如果我們沒(méi)有提供一個(gè)數(shù)值,則將按照默認(rèn)設(shè)置芦圾,只打印一次字符串蛾派。我們通過(guò)為參數(shù) $times
指定默認(rèn)參數(shù)值 1
來(lái)實(shí)現(xiàn)這一點(diǎn)。
在第一次使用 say
時(shí)个少,我們只提供字符串因而函數(shù)只會(huì)將這個(gè)字符串打印一次洪乍。在第二次使用 say
時(shí),我們既提供了字符串夜焦,同時(shí)也提供了一個(gè)參數(shù) 5
壳澳,聲明我們希望說(shuō)(Say)這個(gè)字符串五次。
注意
只有那些位于參數(shù)列表末尾的參數(shù)才能被賦予默認(rèn)參數(shù)值茫经,意即在函數(shù)的參數(shù)列表中擁有默認(rèn)參數(shù)值的參數(shù)不能位于沒(méi)有默認(rèn)參數(shù)值的參數(shù)之前巷波。
這是因?yàn)橹凳前磪?shù)所處的位置依次分配的。舉例來(lái)說(shuō)卸伞,
function func($a, $b = 5)
是有效的抹镊,但function func($a = 5, b)
是無(wú)效的。
可變數(shù)量的參數(shù)
有時(shí)你可能想定義的函數(shù)里面能夠有任意數(shù)量的變量荤傲,也就是參數(shù)數(shù)量是可變的垮耳,這可以通過(guò)使用 ...
來(lái)實(shí)現(xiàn)(將下方示例保存為 function_varargs.php
):
<?php
function sum(...$numbers) {
$acc = 0;
foreach ($numbers as $n) {
$acc += $n;
}
return $acc;
}
echo sum(1, 2, 3, 4);
輸出:
$ php function_varargs.php
10
它是如何工作的
當(dāng)我們聲明一個(gè)諸如 ...$numbers
的參數(shù)時(shí),從此處開(kāi)始直到結(jié)束的所有位置參數(shù)(Positional Arguments)都將被收集并匯集成一個(gè)稱為 $numbers
的數(shù)組。
return
語(yǔ)句
return
語(yǔ)句用于從函數(shù)中返回终佛,也就是中斷函數(shù)俊嗽。我們也可以選擇在中斷函數(shù)時(shí)從函數(shù)中返回一個(gè)值。
示例(保存為 function_return.php
):
<?php
function maximum($x, $y) {
if ($x > $y) {
return $x;
} elseif ($x == $y) {
return 'The numbers are equal';
} else {
return $y;
}
}
echo maximum(2, 3);
輸出:
$ php function_return.php
3
它是如何工作的
maximum
函數(shù)將會(huì)返回參數(shù)中的最大值铃彰,在本例中是提供給函數(shù)的數(shù)值绍豁。它使用一套簡(jiǎn)單的 if...else
語(yǔ)句來(lái)找到較大的那個(gè)值并將其返回。
如果省略了 return
牙捉,則返回值為 NULL
竹揍。
總結(jié)
我們已經(jīng)了解了許多方面的函數(shù),但我們依舊還未覆蓋到所有類型的函數(shù)鹃共。不過(guò)鬼佣,我們已經(jīng)覆蓋到了大部分你每天日常使用都會(huì)使用到的 PHP 函數(shù)。
接下來(lái)霜浴,我們將學(xué)習(xí)一些有趣的概念晶衷,它們被稱為數(shù)據(jù)結(jié)構(gòu)。