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

前言

在所有的编程语言中,方法或者函数,都可以传递一些参数进来进行业务逻辑的处理或者计算。这没什么可说的,但是在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也不要放在前面,这样后面的参数并不会有值,所有的参数都会在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, 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

总结

到此这篇关于关于PHP方法参数的文章就介绍到这了,更多相关PHP方法参数内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

时间: 2021-01-20

PHP页面间参数传递的四种方法详解

我们定义page01.php和page02.php两个php文件,将page01中的内容想办法传递到page02,然后供我们继续使用.--------------------------------------------------------------------------------第一种:使用客户端浏览器的cookie.cookie很容易理解,就是一个临时文件,可以把它看成一个储藏室,浏览器在浏览的过程中记录一些信息,就暂时存放在这里.在page01中设置一个cookie. 复制代码

PHP获取当前日期和时间及格式化方法参数

使用函式 date() 实现 复制代码 代码如下: <?php echo $showtime=date("Y-m-d H:i:s");?> 显示的格式: 年-月-日 小时:分钟:秒 相关时间参数: a - "am" 或是 "pm" A - "AM" 或是 "PM" d - 几日,二位数字,若不足二位则前面补零; 如: "01" 至 "31" D - 星期几

php获取url参数方法总结

本文实例讲述了php获取url参数方法.分享给大家供大家参考.具体如下: 在php中获取url中参数的方法有很多种,其中最简单的就直接使用parse_url函数了,他可以很方便快速的自动解析url参数与值并保存期到对应的数组中,其它的一种方法基本都是正则表达式来操作了. parse_url函数 我们先来了解一下parse_url函数,官方解决 说明: mixed parse_url ( string $url [, int $component = -1 ] ) 本函数解析一个 URL 并返回一

jquery获取url参数及url加参数的方法

使用jquery获取url以及使用jquery获取url参数是我们经常要用到的操作,下面通过文字说明加代码分析的形式给大家解析,具体详情请看下文. 1.jquery获取url很简单,代码如下: 复制代码 代码如下: window.location.href; 其实只是用到了javascript的基础的window对象,并没有用jquery的知识. 2.jquery获取url参数比较复杂,要用到正则表达式,所以学好javascript正则式多么重要的事情 首先看看单纯的通过javascript是如

使用jquery获取url以及jquery获取url参数的实现方法

使用jquery获取url以及使用jquery获取url参数是我们经常要用到的操作 1.jquery获取url很简单,代码如下 window.location.href; 其实只是用到了javascript的基础的window对象,并没有用jquery的知识 2.jquery获取url参数比较复杂,要用到正则表达式,所以学好javascript正则式多么重要的事情 首先看看单纯的通过javascript是如何来获取url中的某个参数 function getUrlParam(name) { va

JS获取url参数、主域名的方法实例分析

本文实例讲述了JS获取url参数.主域名的方法.分享给大家供大家参考,具体如下: <script> alert(location.hostname) alert(location.port) alert(location.pathname) alert(location.search) </script> <script> function winsx(url) //URL传递的参数 { var winurl =url?url:(unescape(window.loca

JS获取url参数,JS发送json格式的POST请求方法

<script type="text/javascript"> 一.获取url所有参数值 function US() { var name, value; var str = location.href; var num = str.indexOf("?"); str = str.substr(num + 1); var arr = str.split("&"); for (var i = 0; i < arr.leng

js中获取URL参数的共用方法getRequest()方法实例详解

下面通过一段代码给大家介绍js中获取URL参数的共用方法getRequest()方法,具体代码如下所示: getRequest : function() { var url = location.search; //获取url中"?"符后的字串 var theRequest = new Object(); if (url.indexOf("?") != -1) { var str = url.substr(1); strs = str.split("&am

JS request函数 用来获取url参数

复制代码 代码如下: function request(strParame) { var args = new Object( ); var query = location.search.substring(1); var pairs = query.split("&"); // Break at ampersand for(var i = 0; i < pairs.length; i++) { var pos = pairs[i].indexOf('='); if (

javascript获取URL参数与参数值的示例代码

复制代码 代码如下: <script>                  function goto_url(url){                      var new_url = "http://shop.usteel.com/index.php?app=list_release";                      var d_date  = getParameter("date",url);                    

jQuery 获取URL参数的插件

例如 当前你的URL是: http://www.jb51.net/index.php?test=1&kk=2 如果想获取test,则可以引入插件后, 用如下方法获取: var test = $.query.get('test'); 如果参数有多个相同的名称 ,则可以这样: var arr = $.query.get('testy'); 输出: [ 值1 , 值2, 值3...] 如果要获取多个相同名称中的某一个,可以这样: var arrayElement = $.query.get('test

js将json格式的对象拼接成复杂的url参数方法

var parseParam=function(param, key){ varparamStr=""; if(paraminstanceof String||param instanceof Number||param instanceof Boolean){ paramStr+="&"+key+"="+encodeURIComponent(param); }else{ $.each(param,function(i){ vark=ke