在所有的編程語言中,方法或者函式,都可以傳遞一些引數進來進行業務邏輯的處理或者計算,這沒什么可說的,但是在PHP中,方法的引數還有許多非常有意思的能力,下面我們就來說說這方面的內容,
參考引數
涉及到值傳遞和參考傳遞的問題,在正常情況下,我們使用值傳遞的時候,變數是進行了拷貝,方法內外的變數不會共享記憶體,也就是說,在方法體中修改了變數的值,方法外部的變數不會產生變化,而參考傳遞則是傳遞的變數的記憶體地值,方法內外的變數可以看做是同一個變數,比如:
$a = 1;
function test(&$arg){
$arg++;
}
test($a);
echo $a; // 2
為引數加上&標識,就表明這個引數是參考傳遞的引數,如果沒有加這個標識,則所有的基本型別引數都會以值的方式進行傳遞,為什么要強調基本型別呢?下面我們用類當引數來測驗一下:
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
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/251394.html
標籤:PHP
下一篇:PHP方法的回傳值
