在全部的编程语言中,方法或者函数,均可以传递一些参数进来进行业务逻辑的处理或者计算。这没什么可说的,可是在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以后,支持全部的普通类型,可是这里要注意的是,只支持普通类型的固定写法。
固定写法是什么意思呢?
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,可是传进去了四个参数,这时咱们可使用三个方法来获取全部的参数:
此外,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)的操做会报错。
关注公众号:【硬核项目经理】获取最新文章
添加微信/QQ好友:【xiaoyuezigonggong/149844827】免费得PHP、项目管理学习资料
知乎、公众号、抖音、头条搜索【硬核项目经理】
B站ID:482780532