鍍金池/ 問答/PHP  C/ 為什么 PHP 函數(shù)只有 Too few arguments 而沒有 Too m

為什么 PHP 函數(shù)只有 Too few arguments 而沒有 Too many arguments 的錯(cuò)誤?

眾所周知,當(dāng)我們傳少了參數(shù)到 PHP 函數(shù)的時(shí)候,會(huì)報(bào) PHP Fatal error: Uncaught ArgumentCountError: Too few arguments to function xxx() 的錯(cuò)誤,比如:

<?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

那如果我們將函數(shù)改寫成下面這樣呢?

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

hello("world");

// Hello

居然不會(huì)拋出 Too many arguments to function hello() 的錯(cuò)誤!難道是 world 這個(gè)字符串被扔掉了而沒有傳進(jìn)去?

將上面的函數(shù)再改一下:

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

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

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

全都已經(jīng)傳進(jìn)去了呀!帶著好奇心搜了一下,發(fā)現(xiàn) StackOverflow 上已經(jīng)有人問過這個(gè)問題了:
https://stackoverflow.com/que...

但是高票回答只是簡簡單單的一句話:

PHP doesn't throw an error on function overload.

然后還從評論區(qū)里翻到了這么一個(gè) bug report:https://bugs.php.net/bug.php?...
官方給出的是 Wont fix,(not a bug but a feature???)

除了上面兩個(gè)鏈接之外,還找到了這個(gè):
http://www.php-internals.com/...
但是看不太懂...


目前我能找到的資料就這些,很好奇但是又不是很清楚是怎么回事,先問幾個(gè)問題:

  1. PHP 的函數(shù)參數(shù)最后是不是有個(gè)隱式的可變長參數(shù)?
  2. PHP 的函數(shù)傳參是怎么實(shí)現(xiàn)的?
  3. 像代碼段 1,是不是其實(shí)正常傳參的時(shí)候函數(shù)內(nèi)部已經(jīng)隱式使用 func_get_args() 幫我們把第一個(gè)參數(shù)值裝到 $name 里面去了?

然后再問一個(gè)問題:

像我這種沒多少底層經(jīng)驗(yàn)的新手,如果想閱讀 PHP 的源碼,該如何讀起?把 php-internals 啃一遍會(huì)有幫助嗎?
回答
編輯回答
陌璃

首先我來說明一下,關(guān)于not a bug but a feature的意思是不是bug,是PHP的新特性,PHP4,PHP5,PHP7都支持,具體可以看這篇文檔 http://www.php.net/manual/zh/...。

對于一個(gè)函數(shù)定義,假設(shè)如下:

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

在函數(shù)內(nèi)部通過func_get_args()函數(shù)就可以取得傳入的參數(shù)。也就是說,這本身就是PHP語法規(guī)則的一部分,假設(shè)調(diào)用PHP的函數(shù)或方法的時(shí)候傳遞的參數(shù)個(gè)數(shù)為N,定義方法或函數(shù)的時(shí)候的參數(shù)個(gè)數(shù)為X,則有 N >= X;另外,如果在定義方法或函數(shù)的時(shí)候?qū)?shù)設(shè)置了默認(rèn)值,則這個(gè)參數(shù)可以不傳。

既然說到這種是PHP本身語法規(guī)則的一部分,我這里告訴你一個(gè)PHP本身的函數(shù)就是通過這個(gè)原理實(shí)現(xiàn)的,那就是compact函數(shù)。

舉個(gè)例子

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

此時(shí)的$d為:

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

在這種情況下就可以傳無限個(gè)參數(shù),然后如果根據(jù)這個(gè)參數(shù)判斷存在以這個(gè)參數(shù)命名的變量,則把這個(gè)變量的值為數(shù)組的value,以參數(shù)名為數(shù)組的key進(jìn)行打包,然后返回一個(gè)數(shù)組。

2017年10月25日 13:33