PHP方法參數(shù)的那點(diǎn)事兒

在所有的編程語言中涩笤,方法或者函數(shù)贸桶,都可以傳遞一些參數(shù)進(jìn)來進(jìn)行業(yè)務(wù)邏輯的處理或者計(jì)算。這沒什么可說的儒拂,但是在PHP中寸潦,方法的參數(shù)還有許多非常有意思的能力,下面我們就來說說這方面的內(nèi)容侣灶。

引用參數(shù)

涉及到值傳遞和引用傳遞的問題甸祭。在正常情況下,我們使用值傳遞的時(shí)候褥影,變量是進(jìn)行了拷貝池户,方法內(nèi)外的變量不會(huì)共享內(nèi)存。也就是說凡怎,在方法體中修改了變量的值校焦,方法外部的變量不會(huì)產(chǎn)生變化。而引用傳遞則是傳遞的變量的內(nèi)存地值统倒。方法內(nèi)外的變量可以看做是同一個(gè)變量寨典,比如:


$a = 1;
function test(&$arg){
    $arg++;
}
test($a);
echo $a; // 2

為參數(shù)加上&標(biāo)識(shí),就表明這個(gè)參數(shù)是引用傳遞的參數(shù)房匆。如果沒有加這個(gè)標(biāo)識(shí)耸成,則所有的基本類型參數(shù)都會(huì)以值的方式進(jìn)行傳遞。為什么要強(qiáng)調(diào)基本類型呢浴鸿?下面我們用類當(dāng)參數(shù)來測(cè)試一下:


class A
{
    public $a = 1;
}
function testA($obj)
{
    $obj->a++;
}

$o = new A();
testA($o);
echo $o->a; // 2

在這個(gè)例子中井氢,我們并沒有使用&標(biāo)識(shí)來表明參數(shù)$obj是引用類型的,但如果傳遞的參數(shù)是對(duì)象的話岳链,那么它默認(rèn)就是進(jìn)行的引用傳遞花竞。如果想讓對(duì)象也是值傳遞呢?抱歉掸哑,在方法參數(shù)中是沒辦法實(shí)現(xiàn)的约急,只能在方法體中使用clone方式對(duì)對(duì)象參數(shù)進(jìn)行克隆零远。


class A
{
    public $a = 1;
}
function testA($obj)
{
    $o = clone $obj;
    $o->a++;
}
$o = new A();
testA($o);
echo $o->a; // 1

關(guān)于值和引用的問題,可以參考設(shè)計(jì)模式中原型模式的講解:
PHP設(shè)計(jì)模式之原型模式

默認(rèn)參數(shù)

參數(shù)是可以有默認(rèn)值的厌蔽,這個(gè)我想大家都應(yīng)該很清楚了牵辣。但是在使用的時(shí)候也需要注意,那就是默認(rèn)參數(shù)不要放在前面躺枕,否則很容易出錯(cuò)服猪,比如:


function testArgsA($a = 1, $b){
    echo $a+$b;
}

testArgs(); // error

function testArgsB($a = 1, $b = 2){
    echo $a+$b;
}

testArgsB(); // 3

function testArgsC($a, $b = 2){
    echo $a+$b;
}

testArgsC(1); // 3

在復(fù)雜的函數(shù)或者緊急的業(yè)務(wù)開發(fā)中,很有可能一個(gè)不小心就會(huì)漏寫參數(shù)拐云,這時(shí)候testArgsA就會(huì)返回錯(cuò)誤了。當(dāng)然近她,這種粗心類的錯(cuò)誤是我們應(yīng)該盡量避免的叉瘩。

當(dāng)指定默認(rèn)值的時(shí)候,我們應(yīng)該根據(jù)參數(shù)的類型進(jìn)行指定粘捎,比如字符串就指定為''薇缅,數(shù)字就指定為數(shù)字類型。當(dāng)不確定參數(shù)是什么類型時(shí)攒磨,建議使用NULL做為默認(rèn)參數(shù)泳桦。


function testArgsD($a = NULL)
{
    if ($a) {
        echo $a;
    }
}

testArgsD(1);
testArgsD('a');

類型聲明

類型聲明是在PHP5之后添加的功能,就像java一樣娩缰,參數(shù)前面加上參數(shù)的類型灸撰,比如:


function testAssignA(int $a = 0)
{
    echo $a;
}

testAssignA(1);
testAssignA("a"); // error

如果參數(shù)的類型不對(duì),直接就會(huì)報(bào)錯(cuò)拼坎。在PHP7以前浮毯,只支持類、數(shù)組和匿名方法的類型聲明泰鸡。在PHP7之后债蓝,支持所有的普通類型,但是這里要注意的是盛龄,只支持普通類型的固定寫法饰迹。

  • Class/interface name
  • self
  • array
  • callable
  • bool
  • float
  • int
  • string

固定寫法是什么意思呢?


function testAssignB(integer $a = 0) // error
{
    echo $a;
}

也就是說余舶,int只能寫int啊鸭,不能使用integer,bool也不能使用boolean欧芽。只能是上面列出的類型關(guān)鍵字莉掂。

類型聲明的好處是什么呢?其實(shí)就是Java這種靜態(tài)語言和PHP這種動(dòng)態(tài)語言之間的差別千扔。動(dòng)態(tài)類型語言的好處就是變量靈活憎妙,不用指定類型库正,方便快速開發(fā)迭代。但問題也在于靈活厘唾,為了靈活褥符,動(dòng)態(tài)語言往往會(huì)在比較或者計(jì)算時(shí)對(duì)變量進(jìn)行自動(dòng)類型轉(zhuǎn)換。如果你對(duì)變量類型轉(zhuǎn)換的理解不清晰的話抚垃,很容易就會(huì)出現(xiàn)各種類型的BUG喷楣。同時(shí),靜態(tài)類型的語言一般都會(huì)有編譯打包鹤树,而動(dòng)態(tài)類型則是在執(zhí)行時(shí)確定變量類型铣焊,所以很少會(huì)進(jìn)行編譯打包,相對(duì)來說運(yùn)行效率也就不如Java之類的編譯后語言了罕伯。

關(guān)于PHP的類型轉(zhuǎn)換問題曲伊,可以參考此前的文章:
PHP中的強(qiáng)制類型轉(zhuǎn)換

Tips一個(gè)小技巧,如果聲明了參數(shù)類型追他,是不能傳遞NULL值的坟募,比如:


function testAssignC(string $a = '')
{
    if ($a) {
        echo __FUNCTION__ . ':' . $a;
    }
}

testAssignC(NULL); // TypeError

這時(shí)有兩種方式可以解決,一是指定默認(rèn)值=NULL邑狸,二是使用?操作符:



function testAssignD(string $a = NULL)
{
    if ($a == NULL) {
        echo 'null';
    }
}

testAssignD(NULL); // null


function testAssignE(?string $a)
{
    if ($a == NULL) {
        echo 'null';
    }
}
testAssignE(NULL); // null

可變數(shù)量參數(shù)

php中的方法可以接收可變數(shù)量的參數(shù)懈糯,比如:


function testMultiArgsA($a)
{
    var_dump(func_get_arg(2));
    var_dump(func_get_args());
    var_dump(func_num_args());
    echo $a;
}

testMultiArgsA(1, 2, 3, 4);

我們只定義了一個(gè)參數(shù)$a,但是傳進(jìn)去了四個(gè)參數(shù)单雾,這時(shí)我們可以使用三個(gè)方法來獲取所有的參數(shù):

  • func_get_arg(int $arg_num)赚哗,獲取參數(shù)列表中的某個(gè)指定位置的參數(shù)
  • func_get_args(),獲取參數(shù)列表
  • func_num_args()铁坎,獲取參數(shù)數(shù)量

此外蜂奸,php還提供了...操作符,用于將可變長(zhǎng)度的參數(shù)定義到一個(gè)參數(shù)變量中硬萍,如:


function testMultiArgsB($a, ...$b)
{
    var_dump(func_get_arg(2));
    var_dump(func_get_args());
    var_dump(func_num_args());
    echo $a;
    var_dump($b); // 除$a以外的
}

testMultiArgsB(1, 2, 3, 4);

和參數(shù)默認(rèn)值一樣扩所,有多個(gè)參數(shù)的情況下,...b也不要放在前面朴乖,這樣后面的參數(shù)并不會(huì)有值祖屏,所有的參數(shù)都會(huì)在b中。不過PHP默認(rèn)已經(jīng)幫我們解決了這個(gè)問題买羞,如果...參數(shù)后面還有參數(shù)的話袁勺,會(huì)直接報(bào)錯(cuò)。

利用這個(gè)操作符畜普,我們還可以很方便的解包一些數(shù)組或可迭代的對(duì)象給方法參數(shù)期丰,例如:


function testMultiArgsC($a, $b){
    echo $a, $b;
}

testMultiArgsC(...[1, 2]);

是不是很有意思,那么我們利用這個(gè)特性來合并一個(gè)數(shù)組會(huì)是什么效果呢?


$array1 = [[1],[2],[3]];
$array2 = [4];
$array3 = [[5],[6],[7]];

$result = array_merge(...$array1); // Legal, of course: $result == [1,2,3];
print_r($result);
$result = array_merge($array2, ...$array1); // $result == [4,1,2,3]
print_r($result);
$result = array_merge(...$array1, $array2); // Fatal error: Cannot use positional argument after argument unpacking.
$result = array_merge(...$array1, ...$array3); // Legal! $result == [1,2,3,5,6,7]
print_r($result);

和方法聲明參數(shù)時(shí)一樣钝荡,在外部使用...操作符給方法傳遞參數(shù)時(shí)街立,也不能在...后面再有其他參數(shù),所以array_merge(...array1,array2)的操作會(huì)報(bào)錯(cuò)埠通。

測(cè)試代碼:
https://github.com/zhangyue0503/dev-blog/blob/master/php/201911/source/PHP%E6%96%B9%E6%B3%95%E5%8F%82%E6%95%B0%E7%9A%84%E9%82%A3%E7%82%B9%E4%BA%8B%E5%84%BF.php

參考文檔:
https://www.php.net/manual/zh/functions.arguments.php
https://www.php.net/manual/zh/functions.arguments.php#121579
https://www.php.net/manual/zh/functions.arguments.php#120580
===========

各自媒體平臺(tái)均可搜索【硬核項(xiàng)目經(jīng)理】

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末赎离,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子端辱,更是在濱河造成了極大的恐慌梁剔,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,348評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件舞蔽,死亡現(xiàn)場(chǎng)離奇詭異荣病,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)喷鸽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,122評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門众雷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人做祝,你說我怎么就攤上這事〖Ω冢” “怎么了混槐?”我有些...
    開封第一講書人閱讀 156,936評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)轩性。 經(jīng)常有香客問我声登,道長(zhǎng),這世上最難降的妖魔是什么揣苏? 我笑而不...
    開封第一講書人閱讀 56,427評(píng)論 1 283
  • 正文 為了忘掉前任悯嗓,我火速辦了婚禮,結(jié)果婚禮上卸察,老公的妹妹穿的比我還像新娘脯厨。我一直安慰自己,他們只是感情好坑质,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,467評(píng)論 6 385
  • 文/花漫 我一把揭開白布合武。 她就那樣靜靜地躺著,像睡著了一般涡扼。 火紅的嫁衣襯著肌膚如雪稼跳。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,785評(píng)論 1 290
  • 那天吃沪,我揣著相機(jī)與錄音汤善,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛红淡,可吹牛的內(nèi)容都是我干的不狮。 我是一名探鬼主播,決...
    沈念sama閱讀 38,931評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼锉屈,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼荤傲!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起颈渊,我...
    開封第一講書人閱讀 37,696評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤遂黍,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后俊嗽,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體雾家,經(jīng)...
    沈念sama閱讀 44,141評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,483評(píng)論 2 327
  • 正文 我和宋清朗相戀三年绍豁,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了芯咧。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,625評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡竹揍,死狀恐怖敬飒,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情芬位,我是刑警寧澤无拗,帶...
    沈念sama閱讀 34,291評(píng)論 4 329
  • 正文 年R本政府宣布,位于F島的核電站昧碉,受9級(jí)特大地震影響英染,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜被饿,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,892評(píng)論 3 312
  • 文/蒙蒙 一四康、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧狭握,春花似錦闪金、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至嗅辣,卻和暖如春撼泛,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背澡谭。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來泰國(guó)打工愿题, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留损俭,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,324評(píng)論 2 360
  • 正文 我出身青樓潘酗,卻偏偏與公主長(zhǎng)得像杆兵,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子仔夺,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,492評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • Welcome 目前網(wǎng)絡(luò)上充斥著大量的陳舊信息琐脏,讓PHP新手誤入歧途,傳播著錯(cuò)誤的實(shí)踐和糟糕的代碼缸兔,這必須得到糾正...
    layjoy閱讀 21,663評(píng)論 7 118
  • Buid-in web server內(nèi)置了一個(gè)簡(jiǎn)單的Web服務(wù)器 把當(dāng)前目錄作為Root Document只需要這...
    Success85閱讀 933評(píng)論 1 1
  • 學(xué)過靜態(tài)語言開發(fā)的朋友對(duì)類型轉(zhuǎn)換不會(huì)陌生日裙,比如Java、C#惰蜜、C++等昂拂。靜態(tài)語言的好處就是變量強(qiáng)制必須指定類型,這...
    ZyBlog閱讀 270評(píng)論 0 0
  • 久違的晴天抛猖,家長(zhǎng)會(huì)格侯。 家長(zhǎng)大會(huì)開好到教室時(shí),離放學(xué)已經(jīng)沒多少時(shí)間了财著。班主任說已經(jīng)安排了三個(gè)家長(zhǎng)分享經(jīng)驗(yàn)联四。 放學(xué)鈴聲...
    飄雪兒5閱讀 7,513評(píng)論 16 22
  • 今天感恩節(jié)哎,感謝一直在我身邊的親朋好友撑教。感恩相遇碎连!感恩不離不棄。 中午開了第一次的黨會(huì)驮履,身份的轉(zhuǎn)變要...
    迷月閃星情閱讀 10,559評(píng)論 0 11