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

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

眾所周知,當(dāng)我們傳少了參數(shù)到 PHP 函數(shù)的時候,會報 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

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

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

hello("world");

// Hello

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

將上面的函數(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)傳進去了呀!帶著好奇心搜了一下,發(fā)現(xiàn) StackOverflow 上已經(jīng)有人問過這個問題了:
https://stackoverflow.com/que...

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

PHP doesn't throw an error on function overload.

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

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


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

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

然后再問一個問題:

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

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

對于一個函數(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ù)為N,定義方法或函數(shù)的時候的參數(shù)個數(shù)為X,則有 N >= X;另外,如果在定義方法或函數(shù)的時候?qū)?shù)設(shè)置了默認值,則這個參數(shù)可以不傳。

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

舉個例子

$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'
];

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

2017年10月25日 13:33