当前位置: 首页 > 后端技术 > PHP

关于PHP方法参数的那些事儿

时间:2023-03-29 16:43:06 PHP

在所有的编程语言中,方法或者函数都可以传入一些参数来进行业务逻辑处理或者计算。这个没什么好说的,但是在PHP中,方法的参数还是有很多很有意思的能力的,下面就来聊聊这方面。引用参数涉及按值传递和按引用传递。一般情况下,当我们按值传递时,变量是被复制的,方法内外的变量是不共享内存的。也就是说,如果在方法体中修改了变量的值,那么方法外的变量是不会改变的。引用传递是传递的变量的内存位置值。方法内外的变量可视为同一个变量,例如:$a=1;functiontest(&$arg){$arg++;}test($a);echo$a;//2是参数加上&标记,表示这个参数是引用传递的参数。如果不加这个标志,所有的基本类型参??数都将按值传递。为什么强调基本类型?让我们使用类作为参数来测试:classA{public$a=1;}functiontestA($obj){$obj->a++;}$o=newA();testA($o);echo$o->一个;//2在这个例子中,我们没有使用&号来表示参数$obj是引用类型,但是如果传递的参数是对象,那么默认是引用传递。如果希望对象按值传递怎么办?抱歉,在方法参数中没有办法实现,只能在方法体中使用clone方法克隆对象参数。A类{public$a=1;}functiontestA($obj){$o=clone$obj;$o->a++;}$o=newA();testA($o);echo$o->a;//1关于取值和引用的问题,可以参考设计模式中原型模式的解释:PHP设计模式原型模式的defaultparameter参数可以有默认值,这个我觉得大家应该很清楚。但是使用的时候也需要注意,就是不要把默认参数放在前面,否则容易出错,比如:functiontestArgsA($a=1,$b){echo$a+$b;}testArgs();//errorfunctiontestArgsB($a=1,$b=2){echo$a+$b;}testArgsB();//3functiontestArgsC($a,$b=2){echo$a+$b;}testArgsC(1);//3在复杂的功能或者紧急的业务开发中,很有可能不小心遗漏了参数,此时testArgsA会返回错误。当然,这种粗心大意的错误是我们应该尽量避免的。在指定默认值的时候,我们应该根据参数的类型来指定,比如字符串指定为'',数字指定为数字类型。当您不确定参数是什么类型时,建议使用NULL作为默认参数。函数testArgsD($a=NULL){if($a){echo$a;}}testArgsD(1);testArgsD('a');typedeclarationtypedeclaration是PHP5之后添加的函数,和java一样,在参数前加上参数的类型,例如:functiontestAssignA(int$a=0){echo$a;}testAssignA(1);testAssignA(“A”);//error如果参数类型不对,直接报错。在PHP7之前,只支持类、数组和匿名方法的类型声明。PHP7之后,所有的常见类型都支持了,但是这里需要注意的是,只支持常见类型的固定写法。Class/interfacenameselfarraycallableboolfloatintstring的固定写法是什么意思?functiontestAssignB(integer$a=0)//error{echo$a;}也就是说int只能写int,不能用integer,bool不能用boolean。只能是上面列出的类型关键字。类型声明有什么好处?其实就是Java这样的静态语言和PHP这样的动态语言的区别。动态类型语言的优点是变量灵活,不需要指定类型,有利于快速开发迭代。但问题还在于灵活性。为了灵活性,动态语言经常在比较或计算时对变量进行自动类型转换。如果对变量类型转换理解不清晰,很容易出现各种类型的BUG。同时,静态类型语言一般都是编译打包,而动态类型是在执行的时候用来判断变量类型,所以很少进行编译打包。相对来说,运行效率不如Java等编译型语言。关于PHP的类型转换,可以参考之前的文章:PHP中的强制类型转换Tips一个小技巧,如果声明了参数类型,就不能传NULL值,例如:functiontestAssignC(string$a=''){如果($a){回显__FUNCTION__。':'。$一个;}}testAssignC(NULL);//此时解决TypeError有两种方法,一种是指定默认值=NULL,另一种是使用?运算符:函数testAssignD(string$a=NULL){if($a==NULL){echo'null';}}testAssignD(NULL);//nullfunctiontestAssignE(?string$a){if($a==NULL){echo'null';}}testAssignE(NULL);//nullvariablenumberofparametersphp中的方法可以接收可变数量的参数,例如:functiontestMultiArgsA($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(),获取参数listfunc_num_args(),获取参数个数此外,php还提供了..操作符,用于将变长参数定义成一个参数变量,如:functiontestMultiArgsB($a,...$b){var_dump(func_get_arg(2));var_dump(func_get_args());var_dump(func_num_args());回声$a;变量转储($b);//}testMultiArgsB(1,2,3,4)除了$a;和参数默认值一样,如果有多个参数,...$b不要放在前面,这样后面的参数就没有值了,所有的参数都在$b里,但是PHP已经默认为我们解决了这个问题。如果参数后面有参数,会直接报错。使用这个运算符,我们还可以轻松地将一些数组或可迭代对象解包到方法参数中,例如:functiontestMultiArgsC($a,$b){echo$a,$b;}testMultiArgsC(...[1,2]);是不是很有意思,那么利用这个特性来合并一个数组会有什么效果呢?$array1=[[1],[2],[3]];$array2=[4];$array3=[[5],[6],[7]];$result=array_merge(...$array1);//当然是合法的:$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);//致命错误:参数解包后不能使用位置参数。$result=array_merge(...$array1,...$array3);//合法的!$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.phphttps://www.php.net/manual/zh/functions.arguments.php#121579https://www.php.net/manual/zh/functions.arguments.php#120580各媒体平台可以搜索【硬核项目经理】