为什么 PHP 函数只有 Too few arguments 而没有 Too many arguments 的错误?

众所周知,当我们传少了参数到 PHP 函数的时候,会报 PHP Fatal error: Uncaught ArgumentCountError: Too few arguments to function xxx() 的错误,比如:

<?php
function hello($name)
{
    echo "Hello, {$name}" . PHP_EOL;
}

hello();

// Fatal error: Uncaught ArgumentCountError: Too few arguments to function hello(), 0 passed in D:\tmp\hello.php on line 7 and exactly 1 expected in D:\tmp\hello.php:2

那如果我们将函数改写成下面这样呢?

<?php
function hello()
{
    echo "Hello" . PHP_EOL;
}

hello("world");

// Hello

居然不会抛出 Too many arguments to function hello() 的错误!难道是 world 这个字符串被扔掉了而没有传进去?

将上面的函数再改一下:

<?php
function hello()
{
    foreach (func_get_args() as $arg)
    {
        echo $arg . PHP_EOL;
    }
}

hello("world");
hello("foo", "bar", "baz");

// world
// foo
// bar
// baz

全都已经传进去了呀!带着好奇心搜了一下,发现 StackOverflow 上已经有人问过这个问题了:
https://stackoverflow.com/que...

但是高票回答只是简简单单的一句话:

PHP doesn't throw an error on function overload.

然后还从评论区里翻到了这么一个 bug report:https://bugs.php.net/bug.php?...
官方给出的是 Wont fix,(not a bug but a feature???)

除了上面两个链接之外,还找到了这个:
http://www.php-internals.com/...
但是看不太懂...


目前我能找到的资料就这些,很好奇但是又不是很清楚是怎么回事,先问几个问题:

  1. PHP 的函数参数最后是不是有个隐式的可变长参数
  2. PHP 的函数传参是怎么实现的?
  3. 像代码段 1,是不是其实正常传参的时候函数内部已经隐式使用 func_get_args() 帮我们把第一个参数值装到 $name 里面去了?

然后再问一个问题:

像我这种没多少底层经验的新手,如果想阅读 PHP 的源码,该如何读起?把 php-internals 啃一遍会有帮助吗?
阅读 9.1k
1 个回答

首先我来说明一下,关于not a bug but a feature的意思是不是bug,是PHP的新特性,PHP4,PHP5,PHP7都支持,具体可以看这篇文档 http://www.php.net/manual/zh/...

对于一个函数定义,假设如下:

function test() {
    func_get_args();
}
test(1,2,3,4);

在函数内部通过func_get_args()函数就可以取得传入的参数。也就是说,这本身就是PHP语法规则的一部分,假设调用PHP的函数或方法的时候传递的参数个数为N,定义方法或函数的时候的参数个数为X,则有 N >= X;另外,如果在定义方法或函数的时候对参数设置了默认值,则这个参数可以不传。

既然说到这种是PHP本身语法规则的一部分,我这里告诉你一个PHP本身的函数就是通过这个原理实现的,那就是compact函数。

举个例子

$a = 'test a';
$b = 'test b';
$c = 'test c';
$d = compact('a','b','c');

此时的$d为:

$d = [
    'a' => 'test a',
    'b' => 'test b',
    'c' => 'test c'
];

在这种情况下就可以传无限个参数,然后如果根据这个参数判断存在以这个参数命名的变量,则把这个变量的值为数组的value,以参数名为数组的key进行打包,然后返回一个数组。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题