缘由

在 Lavavel 框架中,有不少函数支持多种参数,例如:

1
2
3
4
5
6
7
8
collect([
    ['product' => 'Desk', 'price' => 200],
    ['product' => 'Chair', 'price' => 100],
])->contains('product', 'Bookcase');

collect([1, 2, 3, 4, 5])->contains(function ($value, $key) {
    return $value > 5;
});

看起来就好像进行了方法重载,但是 PHP 语法不支持方法重载。那这到底是怎么实现的?

可变参数相关函数

PHP 语法虽然不支持方法重载,但是可以使用可变参数来实现重载的功能

func_num_args()、func_get_arg()、func_get_args()

func_num_args(): 获取参数数量 func_get_arg(int $arg_num): 获取某个参数 func_get_args(): 获取所有参数

例如:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<?php
function sum()
{
    $items = func_get_args();
    echo '共有'.func_num_args()."个参数\n";
    echo '第一个参数是'.func_get_arg(0)."\n";

    $result = 0;
    foreach ($items as $value) {
        $result = $result + $value;
    }

    return $result;
}

var_dump(sum(1,2,3));
var_dump(sum(1,2));

可以看到,sum函数支持多种不同的参数列表,实现了重载的功能 注意,这三个函数,只能用在函数、方法内部而不能在全局作用域中使用,例如:

1
2
<?php
$items = func_get_args();

这样会报错! 也许您是想获取 php 脚本的参数,那么请看下一节。

…$args(…语法)

PHP 5.6 以后,新增了 … 语法糖,来实现可变参数相关功能。用法请看示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
<?php
function sum(...$items)
{
    $result = 0;
    foreach ($items as $value) {
        $result = $result + $value;
    }

    return $result;
}

$arr = [4,5,6];

var_dump(sum(1,2,3));
var_dump(sum(...$arr));  // 等价于 var_dump(sum(4,5,6));

个人感觉,…语法比func_num_args()等函数好用多了,清晰明了。 注意,…只能作为实参、形参在参数列表中使用,其它地方不能用。

形参与实参的数量

本文之前的一个例子:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
<?php
function sum()
{
    $items = func_get_args();
    echo '共有'.func_num_args()."个参数\n";
    echo '第一个参数是'.func_get_arg(0)."\n";

    $result = 0;
    foreach ($items as $value) {
        $result = $result + $value;
    }

    return $result;
}

var_dump(sum1(1,2,3));

我们把代码稍微改动一下,如下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
<?php
function sum($a,$b)   // 改了形参
{
    $items = func_get_args();
    echo '共有'.func_num_args()."个参数\n";
    echo '第一个参数是'.func_get_arg(0)."\n";

    $result = 0;
    foreach ($items as $value) {
        $result = $result + $value;
    }

    return $result;
}

var_dump(sum(1));  // 改了实参

这样会报错,因为我们传入的参数1比接收的参数$a,$b个数要少,导致$b这个参数拿不到值,且$b又没默认值。 用一句比较难懂的话来说就是:实参的数量 要大于或等于 无默认值的形参的数量

cli 模式下命令行参数的获取

写好了 PHP 脚本,但是在运行的时候想传入参数.例如想执行一个脚本,例如用脚本清空某个数据表:

1
php clear_table.php user

那么这个参数user该怎么拿到? 思维活跃的人可能就想着用func_get_args来获取命令行参数,但这样是不行的,因为它只能在函数、方法内部使用。 有如下两种方法:

使用 argv 数组

1
2
<?php
var_dump($argv);

命令行中执行

1
php clear_table.php user

就会输出

1
2
3
4
5
Array
(
    [0] => clear_table.php
    [1] => user
)

使用 getopt 方法

该方法的优点是能够解析命令行参数:

1
2
3
<?php
    $param = getopt('a🅱️c:d::e');
    print_r($param);

命令行中执行

1
php clear_table.php -table_name user -dbname=mydb

脚本执行结果为:

1
2
3
4
5
Array
(
    [table_name] => user
    [dbname]     => mydb
)

参考资料

https://blog.csdn.net/fdipzone/article/details/51945892

https://www.cnblogs.com/xdao/p/php_var_args.html