《簡(jiǎn)明 PHP 教程》07 函數(shù)

函數(shù)是指可重復(fù)使用的程序片段。它們?cè)试S你為某個(gè)代碼塊賦予名字泻骤,允許你通過(guò)這一特殊的名字在你的程序任何地方來(lái)運(yùn)行代碼塊漆羔,并可重復(fù)任何次數(shù)。這就是所謂的調(diào)用函數(shù)狱掂。我們已經(jīng)使用過(guò)了許多內(nèi)置函數(shù)演痒,例如:strlentrim

函數(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)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末阴孟,一起剝皮案震驚了整個(gè)濱河市晌纫,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌永丝,老刑警劉巖锹漱,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異慕嚷,居然都是意外死亡哥牍,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)喝检,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)嗅辣,“玉大人,你說(shuō)我怎么就攤上這事挠说≡杼罚” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵损俭,是天一觀的道長(zhǎng)蛙奖。 經(jīng)常有香客問(wèn)我,道長(zhǎng)杆兵,這世上最難降的妖魔是什么雁仲? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮琐脏,結(jié)果婚禮上攒砖,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好祭衩,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著阅签,像睡著了一般掐暮。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上政钟,一...
    開(kāi)封第一講書(shū)人閱讀 49,036評(píng)論 1 285
  • 那天路克,我揣著相機(jī)與錄音,去河邊找鬼养交。 笑死精算,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的碎连。 我是一名探鬼主播灰羽,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼鱼辙!你這毒婦竟也來(lái)了廉嚼?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤倒戏,失蹤者是張志新(化名)和其女友劉穎怠噪,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體杜跷,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡傍念,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了葛闷。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片憋槐。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖孵运,靈堂內(nèi)的尸體忽然破棺而出秦陋,到底是詐尸還是另有隱情,我是刑警寧澤治笨,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布驳概,位于F島的核電站,受9級(jí)特大地震影響旷赖,放射性物質(zhì)發(fā)生泄漏顺又。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一等孵、第九天 我趴在偏房一處隱蔽的房頂上張望稚照。 院中可真熱鬧,春花似錦、人聲如沸果录。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)弱恒。三九已至辨萍,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間返弹,已是汗流浹背锈玉。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留义起,地道東北人拉背。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像默终,于是被迫代替她去往敵國(guó)和親椅棺。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345