PHP Conference Japan 2024

func_get_args

(PHP 4, PHP 5, PHP 7, PHP 8)

func_get_args傳回包含函式參數列表的陣列

說明

func_get_args(): 陣列

取得函式參數列表的陣列。

這個函式可以與 func_get_arg()func_num_args() 搭配使用,讓使用者自訂函式可以接受不定數量的參數。

參數

這個函式沒有參數。

回傳值

回傳一個陣列,其中每個元素都是目前使用者自訂函式參數列表中對應成員的副本。

錯誤/例外

如果從使用者自訂函式外部呼叫,會產生警告。

範例

範例 #1 func_get_args() 範例

<?php
function foo()
{
$numargs = func_num_args();
echo
"參數數量: $numargs \n";
if (
$numargs >= 2) {
echo
"第二個參數是: " . func_get_arg(1) . "\n";
}
$arg_list = func_get_args();
for (
$i = 0; $i < $numargs; $i++) {
echo
"參數 $i 是: " . $arg_list[$i] . "\n";
}
}

foo(1, 2, 3);
?>

上述範例將輸出:

Number of arguments: 3 
Second argument is: 2
Argument 0 is: 1
Argument 1 is: 2
Argument 2 is: 3

範例 #2 func_get_args() 參照傳遞和值傳遞參數的範例

<?php
function byVal($arg) {
echo
'傳入的參數:', var_export(func_get_args()), PHP_EOL;
$arg = 'baz';
echo
'變更後的參數:', var_export(func_get_args()), PHP_EOL;
}

function
byRef(&$arg) {
echo
'傳入的參數:', var_export(func_get_args()), PHP_EOL;
$arg = 'baz';
echo
'變更後的參數:', var_export(func_get_args()), PHP_EOL;
}

$arg = 'bar';
byVal($arg);
byRef($arg);
?>

上述範例將輸出:


傳入的參數:array (
0 => 'bar',
)
變更後的參數:array (
0 => 'baz',
)
傳入的參數:array (
0 => 'bar',
)
變更後的參數:array (
0 => 'baz',
)

注意事項

備註:

從 PHP 8.0.0 開始,func_*() 系列函式旨在對具名參數大部分透明,方法是將參數視為按位置傳遞,並以預設值替換缺少的參數。此函式會忽略收集未知的具名可變參數。收集的未知具名參數只能透過可變參數存取。

備註:

如果參數是透過引用傳遞的,則對參數的任何更改都會反映在此函式返回的值中。從 PHP 7 開始,如果參數是透過值傳遞的,也會返回目前的值。

注意此函式僅返回傳遞參數的副本,並且不考慮預設(未傳遞)參數。

另請參閱

新增備註

使用者貢獻的備註 12 則備註

T.M.
20 年前
使用動態參數計算平均值的簡單函式
<?php
function average(){
return
array_sum(func_get_args())/func_num_args();
}
print
average(10, 15, 20, 25); // 17.5
?>
cobrattila at gmail dot com
5 年前
如果您想要透過引用取得參數,而不是使用 `func_get_args()`,您可以簡單地使用:

<?php
function args_byref(&...$args) {
// 在此修改 $args 陣列
}
?>

感謝 Markus Malkusch 在 Stackoverflow 上指出這一點。
https://stackoverflow.com/a/29181826/1426064
anderson at francotecnologia dot com
16 年前
如何建立多型/「重載」函式

<?php
function select()
{
$t = '';
$args = func_get_args();
foreach (
$args as &$a) {
$t .= gettype($a) . '|';
$a = mysql_real_escape_string($a);
}
if (
$t != '') {
$t = substr($t, 0, - 1);
}
$sql = '';
switch (
$t) {
case
'integer':
// search by ID
$sql = "id = {$args[0]}";
break;
case
'string':
// search by name
$sql = "name LIKE '%{$args[0]}%'";
break;
case
'string|integer':
// search by name AND status
$sql = "name LIKE '%{$args[0]}%' AND status = {$args[1]}";
break;
case
'string|integer|integer':
// search by name with limit
$sql = "name LIKE '%{$args[0]}%' LIMIT {$args[1]},{$args[2]}";
break;
default:
// :P
$sql = '1 = 2';
}
return
mysql_query('SELECT * FROM table WHERE ' . $sql);
}
$res = select(29); // by ID
$res = select('Anderson'); // by name
$res = select('Anderson', 1); // by name and status
$res = select('Anderson', 0, 5); // by name with limit
?>
daveNO at ovumSPAMdesign dot com
23 年前
<?php
// 如何在 PHP 中模擬具名參數。
// 作者:Dave Benjamin <dave@ovumdesign.com>

// 將 func_get_args() 返回的陣列轉換成一個由名稱/值
// 對組成的陣列,可以被 extract() 處理。
function varargs($args) {
$count = count($args);
for (
$i = 0; $i < $count; $i += 2) {
$result[$args[$i]] = $args[$i + 1];
}

return
$result;
}

// 範例
function test(&$ref1, &$ref2) {
// 預設參數寫在這裡。
$foo = "oof";

// 做一些神奇的事情。
extract(varargs(func_get_args()));

echo
nl2br("\n\$var1 = $var1");
echo
nl2br("\n\$var2 = $var2");
echo
nl2br("\n\$foo = $foo\n\n");

// 修改一些以傳址方式傳遞的變數。
// 注意 func_get_args() 不會傳遞參考,所以它們
// 需要在函式定義中明確宣告。
$ref1 = 42;
$ref2 = 84;
}

$a = 5;
$b = 6;

echo
nl2br("呼叫 test() 之前: \$a = $a\n");
echo
nl2br("呼叫 test() 之前: \$b = $b\n");

// 試著從下一行移除 'foo, "bar"'。
test($a, $b, var1, "abc", var2, "def", foo, "bar");

echo
nl2br("呼叫 test() 之後: \$a = $a\n");
echo
nl2br("呼叫 test() 之後: \$b = $b\n");
?>
foxkeys at gmail dot com
8 年前
合併 func_get_args() 與函式預設值
<?php
class utils {
/**
* @param mixed[] $args
* @param ReflectionMethod $reflectionMethod
*
* @return array
*/
public static function mergeArgsWithDefaults( $args, \ReflectionMethod $reflectionMethod ) {
foreach (
array_slice( $reflectionMethod->getParameters(), count( $args ) ) as $param ) {
/**
* @var ReflectionParameter $param
*/
$args[] = $param->getDefaultValue();
}
return
$args;
}
}

class
sampleParent {
const
USER_FILE_TYPE_FILE = 'FILE';
public function
select( $idUserFile = null, $idUserFileType = self::USER_FILE_TYPE_FILE ) {
echo
'[$idUserFile=>' . $idUserFile . ', $idUserFileType=>' . $idUserFileType, ']<br/>' . PHP_EOL;
}
}

class
sample extends sampleParent {
const
USER_FILE_TYPE_IMG = 'IMG';
public function
select( $idUserFile = null, $idUserFileType = self::USER_FILE_TYPE_IMG ) {
return
call_user_func_array( 'parent::select', \utils::mergeArgsWithDefaults( func_get_args(), new ReflectionMethod( __CLASS__, __FUNCTION__ ) ) );
}
}

$sample1 = new sampleParent();
$sample1->select();//Prints "" / self::USER_FILE_TYPE_FILE
$sample1->select(1);//Prints 1 / self::USER_FILE_TYPE_FILE
$sample1->select(2, 'test 1');//Prints 2 / "test 1"
echo '<br/>' . PHP_EOL;
$sample2 = new sample();
$sample2->select();//Prints "" / self::USER_FILE_TYPE_IMG
$sample2->select(3);//Prints 3 / self::USER_FILE_TYPE_IMG
$sample2->select(4, 'test 2');//Prints 4 / "test 2"
?>
OpenTechnologist
12 年前
請注意,func_get_args() 以及 func_get_arg() 無法讀取/傳遞選用參數。

例如:

<?php
function testfunc($optional = 'this argument is optional..') {
$args = func_get_args();
var_dump($args);
echo
$optional;
}
?>

測試案例 #1
testfunc('argument no longer optional..');

#1 的結果
array(1) {
[0]=> string(20) "argument no longer optional.."
}
argument no longer optional..

測試案例 #2
testfunc('argument no longer optional..','this is an extra argument');

#2 的結果
array(2) {
[0]=> string(29) "argument no longer optional.."
[1]=> string(25) "this is an extra argument"
}
argument no longer optional..

測試案例 #3:-- 結果為空陣列
testfunc();

#3 的結果
array(0) {
}
this argument is optional..
hans at loltek dot net
1 年前
我想要一個參數的關聯式列表,如果其他人也需要的話,我就把它留在這裡。

我希望 PHP 能原生支援這個功能,因為核心實作會比這個使用者端的 backtrace+reflection 實作更快
<?php

/**
* 將函式引數取得為關聯式陣列
* (與 func_get_args() 相同,但帶有鍵值)
*
* @param bool $populateMissingArgumentsWithDefaults 是否用預設值填充陣列中缺少的引數
*
* @return array
*/
function func_get_args_associative(bool $populateMissingArgumentsWithDefaults = false): array
{
$trace = debug_backtrace(0, 2)[1];
$reflection = null;
if (isset(
$trace['class'])) {
$reflection = new \ReflectionMethod($trace['class'], $trace['function']);
} else {
$reflection = new \ReflectionFunction($trace['function']);
}
$ret = [];
foreach (
$reflection->getParameters() as $param) {
if (
array_key_exists($param->getPosition(), $trace['args'])) {
$ret[$param->name] = $trace['args'][$param->getPosition()];
} elseif (
$populateMissingArgumentsWithDefaults) {
// 因為「在可選引數之後宣告的必要引數會被隱式地視為必要引數」的規則:
assert($param->isDefaultValueAvailable(), "我認為所有參數要嘛都在 trace[args] 中,要嘛都有預設值");
$ret[$param->name] = $param->getDefaultValue();
}
}
return
$ret;
}
?>
art at geigel dot com
1 年前
例如,使用 count() 時,func_get_args() 所產生陣列的大小並未將函式定義中已指定預設值的參數納入計算。

範例

function foo($bar=true) {
echo count(func_get_args());
}

foo();
// 顯示 0

foo("bar");
// 顯示 1

當函式在沒有提供值時需要返回預設行為(無論是什麼),且 $bar 的值可以是 true、false、null 等時,這是一個有用的測試條件。
maarten at ba dot be
12 年前
這個函式似乎只返回一個副本,並遺失了它的 byref 資訊,請改用這個不太有效率的變通方法

在撰寫本文時,它目前將所有參數都以參考方式返回,而不是只返回以參考方式傳遞的參數...

<?php
function func_get_args_byref() {
$trace = debug_backtrace();
return
$trace[1]['args'];
}
?>
mitko at edabg dot com
15 年前
<?php
/*
這個例子示範如何使用未知數量的變數引數(by reference)。
func_get_args() 不會傳回引數的參考,但
debug_backtrace() 的 "args" 是傳回參考。
在 PHP 5 中,這沒有特別的意義,因為使用引數參考呼叫
已被棄用並會產生警告。
*/

class foo {

var
$bar = "default bar";

function
foo(/*可變參數*/) {
// func_get_args 傳回引數的副本
// $args = func_get_args();
// debug_backtrace 傳回引數的參考
$stack = debug_backtrace();
$args = array();
if (isset(
$stack[0]["args"]))
for(
$i=0; $i < count($stack[0]["args"]); $i++)
$args[$i] = & $stack[0]["args"][$i];
call_user_func_array(array(&$this, 'bar'), $args);
}


function
bar($bar = NULL) {
if (isset(
$bar))
$this->bar = & $bar;
}
}

$global_bar = "bar global";
$foo = & new foo();
echo
"foo->bar: ".$foo->bar."</br>\n";
$foo->bar = "new bar";
echo
"global_bar: ".$global_bar."</br>\n";
/*
結果:
foo->bar: default bar</br>
global_bar: bar global</br>
*/

$foo = & new foo(&$global_bar);
echo
"foo->bar: ".$foo->bar."</br>\n";
$foo->bar = "new bar";
echo
"global_bar: ".$global_bar."</br>\n";
/*
結果:
foo->bar: bar global</br>
global_bar: new bar</br>
*/

?>
ario [a] mail [dot] utexas [dot] edu
17 年前
「因為此函數依賴當前作用域來決定參數細節,所以它不能用作函數參數。如果您必須傳遞此值,請將結果賦值給一個變數,然後傳遞該變數。」

這表示以下程式碼會產生錯誤

<?php

function foo($list)
{
echo
implode(', ', $list);
}

function
foo2()
{
foo(func_get_args());
}

foo2(1, 2, 3);

?>

然而,您可以透過執行以下操作輕鬆解決此問題

<?php

function foo($list)
{
echo
implode(', ', $list);
}

function
foo2()
{
foo($args = func_get_args());
}

foo2(1, 2, 3);

?>

這會擷取 foo2() 的上下文,使其合法。您將獲得預期的輸出

"1, 2, 3"
匿名
23 年前
您可以使用陣列將不定數量的參數傳遞給函數,同時保持參照的完整性。缺點當然是被呼叫的函數需要知道它的參數在一個陣列中。

<?php
// 顯示 "hello mutated world"
function mutator($args=null) {
$n=count($args);
while(
$i<$n) $args[$i++] = "mutated";
}
$a = "hello";
$b = "strange";
$c = "world";
mutator(array($a, &$b, $c));
echo
"$a $b $c";
?>
To Top