• 首页
  • vue
  • TypeScript
  • JavaScript
  • scss
  • css3
  • html5
  • php
  • MySQL
  • redis
  • jQuery
  • func_get_args()

    (PHP 4, PHP 5, PHP 7)

    返回一个包含函数参数列表的数组

    说明

    func_get_args(void): array

    获取函数参数列表的数组。

    该函数可以配合func_get_arg()和func_num_args()一起使用,从而使得用户自定义函数可以接受自定义个数的参数列表。

    返回值

    返回一个数组,其中每个元素都是目前用户自定义函数的参数列表的相应元素的副本。

    更新日志

    版本说明
    5.3.0该函数可以在参数列表中使用。
    5.3.0If this function is called from the outermost scope of a file which has been included by callingincludeorrequirefrom within a function in the calling file, it now generates a warning and returnsFALSE.(不知道如何翻译跟好,直接参考例2即可明白)

    错误/异常

    在用户自定义函数外调用则会出现错误警告。

    范例

    Example #1func_get_args()例子

    <?php
    function foo()
    {
        $numargs = func_num_args();
        echo "Number of arguments: $numargs<br />\n";
        if ($numargs >= 2) {
            echo "Second argument is: " . func_get_arg(1) . "<br />\n";
        }
        $arg_list = func_get_args();
        for ($i = 0; $i < $numargs; $i++) {
            echo "Argument $i is: " . $arg_list[$i] . "<br />\n";
        }
    }
    foo(1, 2, 3);
    ?>
    

    以上例程会输出:

    Number of arguments: 3<br />
    Second argument is: 2<br />
    Argument 0 is: 1<br />
    Argument 1 is: 2<br />
    Argument 2 is: 3<br />
    

    PHP 5.3 前后使用func_get_args()在的对比

    test.php
    <?php
    function foo() {
        include './fga.inc';
    }
    foo('First arg', 'Second arg');
    ?>
    fga.inc
    <?php
    $args = func_get_args();
    var_export($args);
    ?>
    

    PHP 5.3 版本之前的输出:

    array (
      0 => 'First arg',
      1 => 'Second arg',
    )
    

    PHP 5.3 和之后的版本的输出:

    Warning: func_get_args():  Called from the global scope - no function
    context in /home/torben/Desktop/code/ml/fga.inc on line 3
    false
    

    Example #3func_get_args()example of byref and byval arguments

    <?php
    function byVal($arg) {
        echo 'As passed     : ', var_export(func_get_args()), PHP_EOL;
        $arg = 'baz';
        echo 'After change  : ', var_export(func_get_args()), PHP_EOL;
    }
    function byRef(&$arg) {
        echo 'As passed     : ', var_export(func_get_args()), PHP_EOL;
        $arg = 'baz';
        echo 'After change  : ', var_export(func_get_args()), PHP_EOL;
    }
    $arg = 'bar';
    byVal($arg);
    byRef($arg);
    ?>
    

    以上例程会输出:


    As passed : array (
    0 =>'bar',
    )
    After change : array (
    0 =>'bar',
    )
    As passed : array (
    0 =>'bar',
    )
    After change : array (
    0 =>'baz',
    )

    注释

    Note:

    因为函数依赖于当前作用域以确定参数的细节,所以在5.3.0 以前的版本中不能用作函数的参数。如必须传递此值时,可将结果赋与一个变量,然后用此变量进行传递。

    Note:

    如果参数以引用方式传递,函数对该参数的任何改变将在函数返回后保留。

    Note:该函数仅仅是返回传递参数的一个副本,并且不包含没有传入的默认参数。

    参见

    • func_get_arg() 返回参数列表的某一项
    • func_num_args()Returns the number of arguments passed to the function
    • ReflectionFunctionAbstract::getParameters() 获取参数
    Simple function to calculate average value using dynamic arguments:
    <?php
    function average(){
      return array_sum(func_get_args())/func_num_args();
    }
    print average(10, 15, 20, 25); // 17.5
    ?>
    
    Merge func_get_args() with function defaults
    <?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"
    ?>
    
    How to create a polymorphic/"overloaded" function
    <?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
    ?>
    
    <?php
    /*
    This example demonstrate how to use unknown variable arguments by reference.
    func_get_args() don't return arguments by reference, but 
    debug_backtrace() "args" is by reference.
    In PHP 5 this have no particular sense, because calling with arguments by reference
    is depreciated and produce warning.
    */
    class foo {
      var $bar = "default bar";
      
      function foo(/*variable arguments*/) {
    // func_get_args returns copy of arguments
    //    $args = func_get_args();
    // debug_backtrace returns arguments by reference      
        $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";
    /*
    Result:
    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";
    /*
    Result:
    foo->bar:  bar global</br>
    global_bar: new bar</br>
    */
    ?>
    
    please note that optional parameters are not seen/passed by func_get_args(), as well as func_get_arg().
    ex:
    <?php
    function testfunc($optional = 'this argument is optional..') {
      $args = func_get_args();
      var_dump($args);
      echo $optional;
    }
    ?>
    test case #1:
    testfunc('argument no longer optional..');
    result for #1:
    array(1) {
      [0]=> string(20) "argument no longer optional.."
    }
    argument no longer optional..
    test case #2:
    testfunc('argument no longer optional..','this is an extra argument');
    result for #2:
    array(2) {
      [0]=> string(29) "argument no longer optional.."
      [1]=> string(25) "this is an extra argument"
    }
    argument no longer optional..
    test case #3: -- RESULTS IN AN EMPTY ARRAY
    testfunc();
    result for #3:
    array(0) {
    }
    this argument is optional..
    If you want to get the arguments by reference, instead of func_get_args() you can simply use
    <?php
    function args_byref(&...$args) {
      // Modify the $args array here
    }
    ?>
    Credits should go to Markus Malkusch for pointing this out on Stackoverflow.
    https://stackoverflow.com/a/29181826/1426064
    "Because this function depends on the current scope to determine parameter details, it cannot be used as a function parameter. If you must pass this value, assign the results to a variable, and pass the variable."
    This means that the following code generates an error:
    <?php
    function foo($list)
    {
     echo implode(', ', $list);
    }
    function foo2()
    {
     foo(func_get_args());
    }
    foo2(1, 2, 3);
    ?>
    However, you can easily get around this by doing the following:
    <?php
    function foo($list)
    {
     echo implode(', ', $list);
    }
    function foo2()
    {
     foo($args = func_get_args());
    }
    foo2(1, 2, 3);
    ?>
    This captures the context from foo2(), making this legal. You get the expected output:
    "1, 2, 3"
    <?php
    // How to simulate named parameters in PHP.
    // By Dave Benjamin <dave@ovumdesign.com>
    // Turns the array returned by func_get_args() into an array of name/value
    // pairs that can be processed by extract().
    function varargs($args) {
      $count = count($args);
      for ($i = 0; $i < $count; $i += 2) {
        $result[$args[$i]] = $args[$i + 1];
      }
      
      return $result;
    }
    // Example
    function test(&$ref1, &$ref2) {
      // Default arguments go here.
      $foo = "oof";
      
      // Do some magic.
      extract(varargs(func_get_args()));
      echo nl2br("\n\$var1 = $var1");
      echo nl2br("\n\$var2 = $var2");
      echo nl2br("\n\$foo = $foo\n\n");
      
      // Modify some variables that were passed by reference.
      // Note that func_get_args() doesn't pass references, so they
      // need to be explicitly declared in the function definition.
      $ref1 = 42;
      $ref2 = 84;
    }
    $a = 5;
    $b = 6;
    echo nl2br("Before calling test(): \$a = $a\n");
    echo nl2br("Before calling test(): \$b = $b\n");
    // Try removing the 'foo, "bar"' from the following line.
    test($a, $b, var1, "abc", var2, "def", foo, "bar");
    echo nl2br("After calling test(): \$a = $a\n");
    echo nl2br("After calling test(): \$b = $b\n");
    ?>
    
    You can pass a variable number of arguments to a function whilst keeping references intact by using an array. The disadvantage of course, is that the called function needs to be aware that it's arguments are in an array.
    <?php
    // Prints "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";
    ?>
    
    it seems that this function only returns a copy and loses it's byref information, use this dirty non-efficient workaround instead:
    at the moment of writing it currently returns all of them as references, instead of only the ones who are passed that way...
    <?php
    function func_get_args_byref() {
        $trace = debug_backtrace();
        return $trace[1]['args'];
    }
    ?>
    

    上篇:func_get_arg()

    下篇:func_num_args()