PHP方法參數的那點事兒

在全部的編程語言中,方法或者函數,均可以傳遞一些參數進來進行業務邏輯的處理或者計算。這沒什麼可說的,可是在PHP中,方法的參數還有許多很是有意思的能力,下面咱們就來講說這方面的內容。php

引用參數java

涉及到值傳遞和引用傳遞的問題。在正常狀況下,咱們使用值傳遞的時候,變量是進行了拷貝,方法內外的變量不會共享內存。也就是說,在方法體中修改了變量的值,方法外部的變量不會產生變化。而引用傳遞則是傳遞的變量的內存地值。方法內外的變量能夠看作是同一個變量,好比:git

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

爲參數加上&標識,就代表這個參數是引用傳遞的參數。若是沒有加這個標識,則全部的基本類型參數都會以值的方式進行傳遞。爲何要強調基本類型呢?下面咱們用類當參數來測試一下:github

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

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

在這個例子中,咱們並無使用&標識來代表參數$obj是引用類型的,但若是傳遞的參數是對象的話,那麼它默認就是進行的引用傳遞。若是想讓對象也是值傳遞呢?抱歉,在方法參數中是沒辦法實現的,只能在方法體中使用clone方式對對象參數進行克隆。編程

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

關於值和引用的問題,能夠參考設計模式中原型模式的講解:
PHP設計模式之原型模式設計模式

默認參數數組

參數是能夠有默認值的,這個我想你們都應該很清楚了。可是在使用的時候也須要注意,那就是默認參數不要放在前面,不然很容易出錯,好比:微信

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

在複雜的函數或者緊急的業務開發中,頗有可能一個不當心就會漏寫參數,這時候testArgsA就會返回錯誤了。固然,這種粗心類的錯誤是咱們應該儘可能避免的。編程語言

當指定默認值的時候,咱們應該根據參數的類型進行指定,好比字符串就指定爲'',數字就指定爲數字類型。當不肯定參數是什麼類型時,建議使用NULL作爲默認參數。函數

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

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

類型聲明

類型聲明是在PHP5以後添加的功能,就像java同樣,參數前面加上參數的類型,好比:

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

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

若是參數的類型不對,直接就會報錯。在PHP7之前,只支持類、數組和匿名方法的類型聲明。在PHP7以後,支持全部的普通類型,可是這裏要注意的是,只支持普通類型的固定寫法。

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

固定寫法是什麼意思呢?

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

也就是說,int只能寫int,不能使用integer,bool也不能使用boolean。只能是上面列出的類型關鍵字。

類型聲明的好處是什麼呢?其實就是Java這種靜態語言和PHP這種動態語言之間的差異。動態類型語言的好處就是變量靈活,不用指定類型,方便快速開發迭代。但問題也在於靈活,爲了靈活,動態語言每每會在比較或者計算時對變量進行自動類型轉換。若是你對變量類型轉換的理解不清晰的話,很容易就會出現各類類型的BUG。同時,靜態類型的語言通常都會有編譯打包,而動態類型則是在執行時肯定變量類型,因此不多會進行編譯打包,相對來講運行效率也就不如Java之類的編譯後語言了。

關於PHP的類型轉換問題,能夠參考此前的文章:
PHP中的強制類型轉換

Tips一個小技巧,若是聲明瞭參數類型,是不能傳遞NULL值的,好比:

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

testAssignC(NULL); // TypeError

這時有兩種方式能夠解決,一是指定默認值=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

可變數量參數

php中的方法能夠接收可變數量的參數,好比:

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);

咱們只定義了一個參數$a,可是傳進去了四個參數,這時咱們可使用三個方法來獲取全部的參數:

  • func_get_arg(int $arg_num),獲取參數列表中的某個指定位置的參數
  • func_get_args(),獲取參數列表
  • func_num_args(),獲取參數數量

此外,php還提供了...操做符,用於將可變長度的參數定義到一個參數變量中,如:

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);

和參數默認值同樣,有多個參數的狀況下,...$b也不要放在前面,這樣後面的參數並不會有值,全部的參數都會在$b中。不過PHP默認已經幫咱們解決了這個問題,若是...參數後面還有參數的話,會直接報錯。

利用這個操做符,咱們還能夠很方便的解包一些數組或可迭代的對象給方法參數,例如:

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

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

是否是頗有意思,那麼咱們利用這個特性來合併一個數組會是什麼效果呢?

$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);

和方法聲明參數時同樣,在外部使用...操做符給方法傳遞參數時,也不能在...後面再有其餘參數,因此array_merge(...$array1, $array2)的操做會報錯。

測試代碼:
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

關注公衆號:【硬核項目經理】獲取最新文章

添加微信/QQ好友:【xiaoyuezigonggong/149844827】免費得PHP、項目管理學習資料

知乎、公衆號、抖音、頭條搜索【硬核項目經理】

B站ID:482780532

相關文章
相關標籤/搜索