函数的参数

通过参数列表可以传递信息到函数,即以逗号作为分隔符的表达式列表。参数是从左向右求值的。

PHP 支持按值传递参数(默认),通过引用传递参数以及默认参数。也支持可变长度参数列表

Example #1 向函数传递数组

<?php
function takes_array($input)
{
    echo 
"$input[0] + $input[1] = "$input[0]+$input[1];
}
?>

通过引用传递参数

默认情况下,函数参数通过值传递(因而即使在函数内部改变参数的值,它并不会改变函数外部的值)。如果希望允许函数修改它的参数值,必须通过引用传递参数。

如果想要函数的一个参数总是通过引用传递,可以在函数定义中该参数的前面加上符号 &:

Example #2 用引用传递函数参数

<?php
function add_some_extra(&$string)
{
    
$string .= 'and something extra.';
}
$str 'This is a string, ';
add_some_extra($str);
echo 
$str;    // outputs 'This is a string, and something extra.'
?>

默认参数的值

函数可以定义 C++ 风格的标量参数默认值,如下所示:

Example #3 在函数中使用默认参数

<?php
function makecoffee($type "cappuccino")
{
    return 
"Making a cup of $type.\n";
}
echo 
makecoffee();
echo 
makecoffee(null);
echo 
makecoffee("espresso");
?>

以上例程会输出:

Making a cup of cappuccino.
Making a cup of .
Making a cup of espresso.

PHP 还允许使用数组 array 和特殊类型 NULL 作为默认参数,例如:

Example #4 使用非标量类型作为默认参数

<?php
function makecoffee($types = array("cappuccino"), $coffeeMaker NULL)
{
    
$device is_null($coffeeMaker) ? "hands" $coffeeMaker;
    return 
"Making a cup of ".join(", "$types)." with $device.\n";
}
echo 
makecoffee();
echo 
makecoffee(array("cappuccino""lavazza"), "teapot");
?>

默认值必须是常量表达式,不能是诸如变量,类成员,或者函数调用等。

注意当使用默认参数时,任何默认参数必须放在任何非默认参数的右侧;否则,函数将不会按照预期的情况工作。考虑下面的代码片断:

Example #5 函数默认参数的不正确用法

<?php
function makeyogurt($type "acidophilus"$flavour)
{
    return 
"Making a bowl of $type $flavour.\n";
}

echo 
makeyogurt("raspberry");   // won't work as expected
?>

以上例程会输出:

Warning: Missing argument 2 in call to makeyogurt() in 
/usr/local/etc/httpd/htdocs/phptest/functest.html on line 41
Making a bowl of raspberry .

现在,比较上面的例子和这个例子:

Example #6 函数默认参数正确的用法

<?php
function makeyogurt($flavour$type "acidophilus")
{
    return 
"Making a bowl of $type $flavour.\n";
}

echo 
makeyogurt("raspberry");   // works as expected
?>

以上例程会输出:

Making a bowl of acidophilus raspberry.

Note: 自 PHP 5 起,传引用的参数也可以有默认值。

类型声明

Note:

在PHP 5中,类型声明也被称为类型提示。

类型声明允许函数在调用时要求参数为特定类型。 如果给出的值类型不对,那么将会产生一个错误: 在PHP 5中,这将是一个可恢复的致命错误,而在PHP 7中将会抛出一个TypeError异常。

为了指定一个类型声明,类型应该加到参数名前。这个声明可以通过将参数的默认值设为NULL来实现允许传递NULL

Valid types

Type Description Minimum PHP version
Class/interface name The parameter must be an instanceof the given class or interface name. PHP 5.0.0
self The parameter must be an instanceof the same class as the one the method is defined on. This can only be used on class and instance methods. PHP 5.0.0
array The parameter must be an array. PHP 5.1.0
callable The parameter must be a valid callable. PHP 5.4.0
bool The parameter must be a boolean value. PHP 7.0.0
float The parameter must be a floating point number. PHP 7.0.0
int The parameter must be an integer. PHP 7.0.0
string The parameter must be a string. PHP 7.0.0
Warning

Aliases for the above scalar types are not supported. Instead, they are treated as class or interface names. For example, using boolean as a parameter or return type will require an argument or return value that is an instanceof the class or interface boolean, rather than of type bool:

<?php
 
function test(boolean $param) {}
 
test(true);
 
?>

以上例程会输出:

 Fatal error: Uncaught TypeError: Argument 1 passed to test() must be an instance of boolean, boolean given, called in - on line 1 and defined in -:1
 

范例

Example #7 Basic class type declaration

<?php
class {}
class 
extends {}

// This doesn't extend C.
class {}

function 
f(C $c) {
    echo 
get_class($c)."\n";
}

f(new C);
f(new D);
f(new E);
?>

以上例程会输出:

C
D

Fatal error: Uncaught TypeError: Argument 1 passed to f() must be an instance of C, instance of E given, called in - on line 14 and defined in -:8
Stack trace:
#0 -(14): f(Object(E))
#1 {main}
  thrown in - on line 8

Example #8 Basic interface type declaration

<?php
interface { public function f(); }
class 
implements { public function f() {} }

// This doesn't implement I.
class {}

function 
f(I $i) {
    echo 
get_class($i)."\n";
}

f(new C);
f(new E);
?>

以上例程会输出:

C

Fatal error: Uncaught TypeError: Argument 1 passed to f() must implement interface I, instance of E given, called in - on line 13 and defined in -:8
Stack trace:
#0 -(13): f(Object(E))
#1 {main}
  thrown in - on line 8

Example #9 Nullable type declaration

<?php
class {}

function 
f(C $c null) {
    
var_dump($c);
}

f(new C);
f(null);
?>

以上例程会输出:

object(C)#1 (0) {
}
NULL

严格类型

默认情况下,如果能做到的话,PHP将会强迫错误类型的值转为函数期望的标量类型。 例如,一个函数的一个参数期望是string,但传入的是integer,最终函数得到的将会是一个string类型的值。

可以基于每一个文件开启严格模式。在严格模式中,只有一个与类型声明完全相符的变量才会被接受,否则将会抛出一个TypeError。 唯一的一个例外是可以将integer传给一个期望float的函数。

使用 declare 语句和strict_types 声明来启用严格模式:

Caution

启用严格模式同时也会影响返回值类型声明.

Note:

严格类型适用于在启用严格模式的文件内的函数调用,而不是在那个文件内声明的函数。 一个没有启用严格模式的文件内调用了一个在启用严格模式的文件中定义的函数,那么将会遵循调用者的偏好(弱类型),而这个值将会被转换。

Note:

严格类型仅用于标量类型声明,也正是因为如此,这需要PHP 7.0.0 或更新版本,因为标量类型声明也是在那个版本中添加的。

Example #10 Strict typing

<?php
declare(strict_types=1);

function 
sum(int $aint $b) {
    return 
$a $b;
}

var_dump(sum(12));
var_dump(sum(1.52.5));
?>

以上例程会输出:

int(3)

Fatal error: Uncaught TypeError: Argument 1 passed to sum() must be of the type integer, float given, called in - on line 9 and defined in -:4
Stack trace:
#0 -(9): sum(1.5, 2.5)
#1 {main}
  thrown in - on line 4

Example #11 Weak typing

<?php
function sum(int $aint $b) {
    return 
$a $b;
}

var_dump(sum(12));

// These will be coerced to integers: note the output below!
var_dump(sum(1.52.5));
?>

以上例程会输出:

int(3)
int(3)

Example #12 Catching TypeError

<?php
declare(strict_types=1);

function 
sum(int $aint $b) {
    return 
$a $b;
}

try {
    
var_dump(sum(12));
    
var_dump(sum(1.52.5));
} catch (
TypeError $e) {
    echo 
'Error: '.$e->getMessage();
}
?>

以上例程会输出:

int(3)
Error: Argument 1 passed to sum() must be of the type integer, float given, called in - on line 10

可变数量的参数列表

PHP 在用户自定义函数中支持可变数量的参数列表。在 PHP 5.6 及以上的版本中,由 ... 语法实现;在 PHP 5.5 及更早版本中,使用函数 func_num_args()func_get_arg(),和 func_get_args()

... in PHP 5.6+

In PHP 5.6 and later, argument lists may include the ... token to denote that the function accepts a variable number of arguments. The arguments will be passed into the given variable as an array; for example:

Example #13 Using ... to access variable arguments

<?php
function sum(...$numbers) {
    
$acc 0;
    foreach (
$numbers as $n) {
        
$acc += $n;
    }
    return 
$acc;
}

echo 
sum(1234);
?>

以上例程会输出:

10

You can also use ... when calling functions to unpack an array or Traversable variable or literal into the argument list:

Example #14 Using ... to provide arguments

<?php
function add($a$b) {
    return 
$a $b;
}

echo 
add(...[12])."\n";

$a = [12];
echo 
add(...$a);
?>

以上例程会输出:

3
3

You may specify normal positional arguments before the ... token. In this case, only the trailing arguments that don't match a positional argument will be added to the array generated by ....

It is also possible to add a type hint before the ... token. If this is present, then all arguments captured by ... must be objects of the hinted class.

Example #15 Type hinted variable arguments

<?php
function total_intervals($unitDateInterval ...$intervals) {
    
$time 0;
    foreach (
$intervals as $interval) {
        
$time += $interval->$unit;
    }
    return 
$time;
}

$a = new DateInterval('P1D');
$b = new DateInterval('P2D');
echo 
total_intervals('d'$a$b).' days';

// This will fail, since null isn't a DateInterval object.
echo total_intervals('d'null);
?>

以上例程会输出:

3 days
Catchable fatal error: Argument 2 passed to total_intervals() must be an instance of DateInterval, null given, called in - on line 14 and defined in - on line 2

Finally, you may also pass variable arguments by reference by prefixing the ... with an ampersand (&).

Older versions of PHP

No special syntax is required to note that a function is variadic; however access to the function's arguments must use func_num_args(), func_get_arg() and func_get_args().

The first example above would be implemented as follows in PHP 5.5 and earlier:

Example #16 Accessing variable arguments in PHP 5.5 and earlier

<?php
function sum() {
    
$acc 0;
    foreach (
func_get_args() as $n) {
        
$acc += $n;
    }
    return 
$acc;
}

echo 
sum(1234);
?>

以上例程会输出:

10

User Contributed Notes

dmitry dot balabka at gmail dot com 13-Nov-2018 09:47
There is a possibility to use parent keyword as type hint which is not mentioned in the documentation.

Following code snippet will be executed w/o errors on PHP version 7. In this example, parent keyword is referencing on ParentClass instead of ClassTrait.
<?php
namespace TestTypeHints;

class
ParentClass
{
    public function
someMethod()
    {
        echo
'Some method called' . \PHP_EOL;
    }
}

trait
ClassTrait
{
    private
$original;

    public function
__construct(parent $original)
    {
       
$this->original = $original;
    }

    protected function
getOriginal(): parent
   
{
        return
$this->original;
    }
}

class
Implementation extends ParentClass
{
    use
ClassTrait;

    public function
callSomeMethod()
    {
       
$this->getOriginal()->someMethod();
    }
}

$obj = new Implementation(new ParentClass());
$obj->callSomeMethod();
?>

Outputs:
Some method called
iqravi dot bhushan at gmail dot com 16-May-2018 05:21
You can pass a function as an argument too.

<?php

   
function sum($numbers){
       
$acc = 0;       
        foreach (
$numbers as $key => $value) {
           
$acc += $value;
        }
        return
$acc;
    }

    function
generateString(){
       
$x = array(1,2,3,4,5,6,7);
        return
$x;
    }
   
    echo
sum(generateString());
?>
Anonymous 12-Mar-2018 01:35
Notice that only order matters. Example:

function f($x='a', $y='b'){
   $output = $x.$y;
   echo $output;
}
f($y='c',$x='d');

This will print 'cd'.

If we call function like this
f($y='c')

actually $x in function gets value of 'c' and $y takes default value, as it just fills parameters in order specified so output will be 'cb'. Names have no meaning in function call. This may be confusing if you are coming from python for example.
boan dot web at outlook dot com 08-Feb-2018 11:27
Quote:

"The declaration can be made to accept NULL values if the default value of the parameter is set to NULL."

But you can do this (PHP 7.1+):

<?php
function foo(?string $bar) {
   
//...
}

foo(); // Fatal error
foo(null); // Okay
foo('Hello world'); // Okay
?>
igorsantos07 at gmail dot com 27-Dec-2017 05:06
PHP 7+ does type coercion if strict typing is not enabled, but there's a small gotcha: it won't convert null values into anything.

You must explicitly set your default argument value to be null (as explained in this page) so your function can also receive nulls.

For instance, if you type an argument as "string", but pass a null variable into it, you might expect to receive an empty string, but actually, PHP will yell at you a TypeError.

<?php
function null_string_wrong(string $str) {
 
var_dump($str);
}
function
null_string_correct(string $str = null) {
 
var_dump($str);
}
$null = null;
null_string_wrong('a');     //string(1) "a"
null_string_correct('a');   //string(1) "a"
null_string_correct();      //NULL
null_string_correct($null); //NULL
null_string_wrong($null);   //TypeError thrown
?>
info at keraweb dot nl 21-Sep-2017 09:25
You can use a class constant as a default parameter.

<?php

class A {
    const
FOO = 'default';
    function
bar( $val = self::FOO ) {
        echo
$val;
    }
}

$a = new A();
$a->bar(); // Will echo "default"
Hayley Watson 30-Aug-2017 11:41
There are fewer restrictions on using ... to supply multiple arguments to a function call than there are on using it to declare a variadic parameter in the function declaration. In particular, it can be used more than once to unpack arguments, provided that all such uses come after any positional arguments.

<?php

$array1
= [[1],[2],[3]];
$array2 = [4];
$array3 = [[5],[6],[7]];

$result = array_merge(...$array1); // Legal, of course: $result == [1,2,3];
$result = array_merge($array2, ...$array1); // $result == [4,1,2,3]
$result = array_merge(...$array1, $array2); // Fatal error: Cannot use positional argument after argument unpacking.
$result = array_merge(...$array1, ...$array3); // Legal! $result == [1,2,3,5,6,7]
?>

The Right Thing for the error case above would be for $result==[1,2,3,4], but this isn't yet (v7.1.8) supported.
Hayley Watson 16-Aug-2017 12:50
If you use ... in a function's parameter list, you can use it only once for obvious reasons. Less obvious is that it has to be on the LAST parameter; as the manual puts it: "You may specify normal positional arguments BEFORE the ... token. (emphasis mine).

<?php
function variadic($first, ...$most, $last)
{
/*etc.*/}

variadic(1, 2, 3, 4, 5);
?>
results in a fatal error, even though it looks like the Thing To Do™ would be to set $first to 1, $most to [2, 3, 4], and $last to 5.
g dot sokol99 at g-sokol dot info 03-Feb-2017 08:55
Nullable arguments:

<?php

class C {}

function
foo(?C $a)
{
   
var_dump($a);
}

foo(null);

foo();
?>

Output:

NULL
PHP Warning:  Uncaught ArgumentCountError: Too few arguments to function foo(), 0 passed in php shell code on line 1 and exactly 1 expected in php shell code:1
Stack trace:
#0 php shell code(1): foo()
#1 {main}
  thrown in php shell code on line 1

Usage of "?" Is also possible with "string", "int", "array" and so on primitive types (which is strange). Also unliKe "= null" "?" can be passed not only for tail of arguments, e.g.:
<?php
function foo(?string $a, string $b) {}
?>
gabriel at figdice dot org 11-Aug-2016 07:05
A function's argument that is an object, will have its properties modified by the function although you don't need to pass it by reference.

<?php
$x
= new stdClass();
$x->prop = 1;

function
f ( $o ) // Notice the absence of &
{
 
$o->prop ++;
}

f($x);

echo
$x->prop; // shows: 2
?>

This is different for arrays:

<?php
$y
= [ 'prop' => 1 ];

function
g( $a )
{
 
$a['prop'] ++;
  echo
$a['prop'];  // shows: 2
}

g($y);

echo
$y['prop'];  // shows: 1
?>
maduro_0 at hotmail dot com 25-Apr-2016 03:56
This will work

function test($a,$b){
    echo 'yes it works';
    echo $a;
    echo $b;
}

echo test('1','2','3','2');

This wouldn't work

function test($a,$b){
    echo 'yes it works';
    echo $a;
    echo $b;
}

echo test('1');
catman at esteticas dot se 07-Feb-2016 01:06
I wondered if variable length argument lists and references works together, and what the syntax might be. It is not mentioned explicitly yet in the php manual as far as I can find. But other sources mention the following syntax "&...$variable" that works in php  5.6.16.

<?php
function foo(&...$args)
{
   
$i = 0;
    foreach (
$args as &$arg) {
       
$arg = ++$i;
    }
}
foo($a, $b, $c);
echo
'a = ', $a, ', b = ', $b, ', c = ', $c;
?>
Gives
a = 1, b = 2, c = 3
ohcc at 163 dot com 08-Nov-2015 09:23
As of PHP 5.6, you can use an array as arguments when calling a function with the ... $args syntax.

<?php
    $args
= array('wu','WU','wuxiancheng.cn');
   
$string = str_replace(...$args);
    echo
$string;
?>

Ha ha, is that interesting and powerful?

Also you can use it like this

<?php
    $args
= array('WU','wuxiancheng.cn');
   
$string = str_replace('wu', ...$args);
    echo
$string;
?>

It also can be used to define a user function.

<?php
   
function wxc ($arg1, $arg2, ...$otherArgs){
        echo
'<pre>';
       
print_r($otherArgs);
       
print_r(func_get_args());
        echo
'</pre>';
    }
   
wxc (1, 2, ...array(3,4,5));
?>

REMEMBER this: ... $args is not supported in PHP 5.5 and older versions.
d_maley at hotmail dot com 26-Aug-2015 09:12
If you define your functions in the following way, you can call them whilst only specifying the default parameters you need

1. Define your function with its mandatory parameters, and an optional array

2. Declare your optional parameters as local variables

3. The crux: replace the value of any optional parameters that you have passed via the array, using PHP's facility to interpret variable variable names. This line is identical for every function

4. Call the function, passing its mandatory parameters, and only those optional parameters that you require

For example,

function test_params($a, $b, $arrOptionalParams = array()) {
  $c = 'sat';
  $d = 'mat';
  foreach($arrOptionalParams as $key => $value) ${$key} = $value;
  echo "$a $b $c on the $d";
}

and then call it like this

test_params('The', 'dog', array('c' => 'stood', 'd' => 'donkey'));
test_params('The', 'cat', array('d' => 'donkey'));
test_params('A', 'dog', array('c' => 'stood'));

Results:

The dog stood on the donkey
The cat sat on the donkey
A dog stood on the mat
rich at richware dot net 08-May-2015 05:27
How to pass a class as an argument? This is simple:

<?php
class TMath {
    private
$_Total;
    function
Sum() {
       
$this->_Total = 0;
        foreach (
func_get_args() as $n) {
           
$this->_Total += $n;
        }
    }
    function
Total() {
        return
$this->_Total;
    }
}
   
$myMath = new TMath();
   
$myMath->Sum(1,2,3);
   
ShowTotal($myMath);

    function
ShowTotal($aMath) {
        echo
$aMath->Total().'<br/>';
    }
php at richardneill dot org 28-Mar-2015 07:24
To experiment on performance of pass-by-reference and pass-by-value, I used this  script. Conclusions are below.

#!/usr/bin/php
<?php
function sum($array,$max){   //For Reference, use:  "&$array"
   
$sum=0;
    for (
$i=0; $i<2; $i++){
       
#$array[$i]++;        //Uncomment this line to modify the array within the function.
       
$sum += $array[$i]; 
    }
    return (
$sum);
}

$max = 1E7                  //10 M data points.
$data = range(0,$max,1);

$start = microtime(true);
for (
$x = 0 ; $x < 100; $x++){
   
$sum = sum($data, $max);
}
$end microtime(true);
echo
"Time: ".($end - $start)." s\n";

/* Run times:
#    PASS BY    MODIFIED?   Time
-    -------    ---------   ----
1    value      no          56 us
2    reference  no          58 us

3    valuue     yes         129 s
4    reference  yes         66 us

Conclusions:

1. PHP is already smart about zero-copy / copy-on-write. A function call does NOT copy the data unless it needs to; the data is
   only copied on write. That's why  #1 and #2 take similar times, whereas #3 takes 2 million times longer than #4.
   [You never need to use &$array to ask the compiler to do a zero-copy optimisation; it can work that out for itself.]

2. You do use &$array  to tell the compiler "it is OK for the function to over-write my argument in place, I don't need the original
   any more." This can make a huge difference to performance when we have large amounts of memory to copy.
   (This is the only way it is done in C, arrays are always passed as pointers)

3. The other use of & is as a way to specify where data should be *returned*. (e.g. as used by exec() ).
   (This is a C-like way of passing pointers for outputs, whereas PHP functions normally return complex types, or multiple answers
   in an array)

4. It's  unhelpful that only the function definition has &. The caller should have it, at least as syntactic sugar. Otherwise
   it leads to unreadable code: because the person reading the function call doesn't expect it to pass by reference. At the moment,
   it's necessary to write a by-reference function call with a comment, thus:
    $sum = sum($data,$max);  //warning, $data passed by reference, and may be modified.

5. Sometimes, pass by reference could be at the choice of the caller, NOT the function definitition. PHP doesn't allow it, but it
   would be meaningful for the caller to decide to pass data in as a reference. i.e. "I'm done with the variable, it's OK to stomp
   on it in memory".
*/
?>
lucas dot ekrause at gmail dot com 18-Jun-2014 08:40
In addition to jcaplan@bogus.amazon.com's comment (http://www.php.net/manual/de/functions.arguments.php#62803) you could also simply write
<?php
function f($x=4){echo $x."\n";}
function
g($x=null){for($i=0; $i<2; $i++){call_user_func_array("f", !is_null($x) ? array($x) : array());}}
?>
aasasdasdf at yandex dot ru 12-Apr-2014 12:34
As of PHP 5.5.10, it seems that a variable will be separated from its value if defined right in a function call:

php > error_reporting(E_ALL);
php > function a(&$b) {$b = 1;}
php > a($q = 2); var_dump($q);
Strict Standards: Only variables should be passed by reference in php shell code on line 1
int(2)
php > $w = 3; a($w); var_dump($w);
int(1)

Notice that it's still fine to use a variable that is not defined at all:

php > a($e); var_dump($e);
int(1)
Horst Schirmeier 08-Jan-2014 11:58
Editor's note: what is expected here by the parser is a non-evaluated expression. An operand and two constants requires evaluation, which is not done by the parser. However, this feature is included as of PHP 5.6.0. See this page for more information: http://php.net/migration56.new-features#migration56.new-features.const-scalar-exprs
--------

"The default value must be a constant expression" is misleading (or even wrong).  PHP 5.4.4 fails to parse this function definition:

function htmlspecialchars_latin1($s, $flags = ENT_COMPAT | ENT_HTML401) {}

This yields a " PHP Parse error:  syntax error, unexpected '|', expecting ')' " although ENT_COMPAT|ENT_HTML401 is certainly what a compiler-affine person would call a "constant expression".

The obvious workaround is to use a single special value ($flags = NULL) as the default, and to set it to the desired value in the function's body (if ($flags === NULL) { $flags = ENT_COMPAT | ENT_HTML401; }).
post at auge8472 dot de 18-Jul-2013 08:48
I needed a way to decide between two possible values for one function parameter. I didn't want to decide it before calling the function but wanted to do the constraint inside the function call.

$foo = 1;
$bar = 2;

function foobar($val) {
    echo $val;
    }

foobar(isset($foo) ? $foo : $bar);

// output: 1

$bar = 2;

function foobar($val) {
    echo $val;
    }

foobar(isset($foo) ? $foo : $bar);

// output: 2
ravenswd at gmail dot com 08-Jul-2013 02:30
Be careful when passing arguments by reference, it can cause unexpected side-effects if one is not careful.

I had a program designed to sweep through directories and subdirectories and report on the total number of files, and the total size of all files. Since it needed to return two values, I used variables passed by reference.

In one spot in the program, I didn't need the values of those variables after they were returned, so I just used a garbage variable named $ignore instead. This caused a curious bug which took me a while to track down, because the effects of the bug were in a different part of the program than the place where I had made a mistake.

Since the same variable was used for both parameters passed by reference, they ended up both pointing to the same physical location in memory, so changing one of them caused both of them to change. The code below is an excerpt of my program, stripped down to just the few lines necessary to illustrate what was happening:

<?php
sweep
($ignore, $ignore);
// no errors occur here

function sweep ( &$filecount, &$bytecount ) {
 
$filecount = 1;
 
$bytecount = 1024;
  print
"Files: $filecount - Size: $bytecount"// prints "Files: 1024 - Size: 1024"
}
?>
jacob at jacobweber dot com 13-Jun-2011 02:05
This page states:

"Note that when using default arguments, any defaults should be on the right side of any non-default arguments; otherwise, things will not work as expected."

There seems to be one exception to this. Say you're using type-hinting for an argument, but you want to allow it to be NULL, and you want additional required arguments to the right of it. PHP allows this, as long as you give it the type-hinted argument a default value of NULL. For example:

<?php
function sample(ClassA $a = NULL, $b) {
}
sample(new ClassA(), ''); // success
sample(new ClassB(), ''); // failure; wrong type
sample(NULL, ''); // success
sample(new ClassA()); // failure; missing second argument
?>
carlos at wfmh dot org dot pl dot REMOVE dot COM 15-Jun-2010 04:48
You can use (very) limited signatures for your functions, specifing type of arguments allowed.

For example:

public function Right( My_Class $a, array $b )

tells first argument have to by object of My_Class, second an array. My_Class means that you can pass also object of class that either extends My_Class or implements (if My_Class is abstract class) My_Class. If you need exactly My_Class you need to either make it final, or add some code to check what $a really.

Also note, that (unfortunately) "array" is the only built-in type you can use in signature. Any other types i.e.:

public function Wrong( string $a, boolean $b )

will cause an error, because PHP will complain that $a is not an *object* of class string (and $b is not an object of class boolean).

So if you need to know if $a is a string or $b bool, you need to write some code in your function body and i.e. throw exception if you detect type mismatch (or you can try to cast if it's doable).
rburnap at intelligent dash imaging dot com 13-May-2010 05:19
This may be helpful when you need to call an arbitrary function known only at runtime:

You can call a function as a variable name.
<?php

function foo(){
    echo
"\nfoo()";
}

function
callfunc($x, $y = '')
{
    if(
$y=='' )
    {
        if(
$x=='' )
             echo
"\nempty";
        else
$x();
    }
    else
        
$y->$x();
}

class
cbar {
    public function
fcatch(){ echo "\nfcatch"; }
}

$x = '';
callfunc($x);
$x = 'foo';
callfunc($x);
$o = new cbar();
$x = 'fcatch';
callfunc($x, $o);
echo
"\n\n";
?>

The code will output

empty
foo()
fcatch
mracky at pacbell dot net 29-Mar-2010 09:40
Nothing was written here about argument types as part of the function definition.

When working with classes, the class name can be used as argument type.  This acts as a reminder to the user of the class, as well as a prototype for php  control. (At least in php 5 -- did not check 4).

<?php
class foo {
  public
$data;
  public function
__construct($dd)
  {
   
$this->data = $dd;
  }
};

class
test {
  public
$bar;

  public function
__construct(foo $arg) // Strict typing for argument
 
{
   
$this->bar = $arg;
  }
  public function
dump()
  {
    echo
$this->bar->data . "\n";
  }

};

$A = new foo(25);
$Test1 = new test($A);
$Test1->dump();
$Test2 = new test(10); // wrong argument for testing

?>
outputs:
25
PHP Fatal error:  Argument 1 passed to test::__construct() must be an object of class foo, called in testArgType.php on line 27 and defined in testArgType.php on line 13
pigiman at gmail dot com 23-Mar-2010 09:37
Hey,

I started to learn for the Zend Certificate exam a few days ago and I got stuck with one unanswered-well question.
This is the question:
"Absent any actual need for choosing one method over the other, does passing arrays by value to a read-only function reduce performance compared to passing them by reference?'

This question answered by Zend support team at Zend.com:

"A copy of the original $array is created within the function scope. Once the function terminates, the scope is removed and the copy of $array with it." (By massimilianoc)

Have a nice day!

Shaked KO
allankelly at gmail dot com 21-Mar-2009 02:34
I like to pass an associative array as an argument. This is reminiscent of a Perl technique and can be tested with is_array. For example:
<?php
function div( $opt )
{
   
$class = '';
   
$text  = '';
    if(
is_array( $opt ) )
    {
        foreach(
$opt as $k => $v )
        {
            switch(
$k )
            {
                case
'class': $class = "class = '$v'";
                                 break;
                case
'text': $text = $v;
                                 break;
            }
        }
    }
    else
    {
       
$text = $opt;
    }
    return
"<div $class>$text</div>";
}
?>
herenvardoREMOVEatSTUFFgmailINdotCAPScom 17-Jan-2009 12:48
There is a nice trick to emulate variables/function calls/etc as default values:

<?php
$myVar
= "Using a variable as a default value!";

function
myFunction($myArgument=null) {
    if(
$myArgument===null)
       
$myArgument = $GLOBALS["myVar"];
    echo
$myArgument;
}

// Outputs "Hello World!":
myFunction("Hello World!");
// Outputs "Using a variable as a default value!":
myFunction();
// Outputs the same again:
myFunction(null);
// Outputs "Changing the variable affects the function!":
$myVar = "Changing the variable affects the function!";
myFunction();
?>
In general, you define the default value as null (or whatever constant you like), and then check for that value at the start of the function, computing the actual default if needed, before using the argument for actual work.
Building upon this, it's also easy to provide fallback behaviors when the argument given is not valid: simply put a default that is known to be invalid in the prototype, and then check for general validity instead of a specific value: if the argument is not valid (either not given, so the default is used, or an invalid value was given), the function computes a (valid) default to use.
Don dot hosek at gmail dot com 20-Nov-2007 05:50
Actually the use of class or global constants does buy us something. It helps enforce the DRY (don't repeat yourself) principle.
conciseusa at yahoo[nospammm] dot com 22-Apr-2007 08:03
With regards to:

It is also possible to force a parameter type using this syntax. I couldn't see it in the documentation.
function foo(myclass par) { }

I think you are referring to Type Hinting. It is documented here: http://ch2.php.net/language.oop5.typehinting
pdenny at magmic dot com 18-Feb-2007 09:43
Note that constants can also be used as default argument values
so the following code:

  define('TEST_CONSTANT','Works!');
  function testThis($var=TEST_CONSTANT) {
      echo "Passing constants as default values $var";
  }
  testThis();

will produce :

Passing constants as default values Works!

(I tried this in both PHP 4 and 5)
John 15-Nov-2006 03:20
This might be documented somewhere OR obvious to most, but when passing an argument by reference (as of PHP 5.04) you can assign a value to an argument variable in the function call. For example:

function my_function($arg1, &$arg2) {
  if ($arg1 == true) {
    $arg2 = true;
  }
}
my_function(true, $arg2 = false);
echo $arg2;

outputs 1 (true)

my_function(false, $arg2 = false);
echo $arg2;

outputs 0 (false)
keuleu at hotmail dot com 19-Oct-2006 02:59
I ran into the problem that jcaplan mentionned. I had just finished building 2 handler classes and one interface.

During my testing I realized that my handlers were not initializing their variables to their default values when my interface was calling them with 'null' values:

this is a simplified illustration:

<?php

function some_function($v1='value1',$v2='value2',$v3='value3'){
  echo
$v1.',  ';
  echo
$v2.',  ';
  echo
$v3;
}

some_function(); //this will behave as expected, displaying 'value1,  value2,  value3'
some_function(null,null,null); //this on the other hand will display ',  ,' since the variables will take the null value.
?>

I came to about the same conclusion as jcaplan. To force your function parameters to take a default value when a null is passed you need to include a conditionnal assignment inside the function definition.

<?php
function some_function($v1='value1',$v2='value1',$v3=null){
 
$v1=(is_null($v1)?'value1':$v1);
 
$v2=(is_null($v2)?'value2':$v2);
 
$v3=(is_null($v3)?'value3':$v3);
  echo
$v1;
  echo
$v2;
  echo
$v3;
}
/*
The default value whether null or an actual value is not so important in the parameter list, what is important is that you include it to allow a default behavior. The default value in the declaration becomes more important at this point:
*/
?>
jcaplan at bogus dot amazon dot com 09-Mar-2006 03:11
In function calls, PHP clearly distinguishes between missing arguments and present but empty arguments.  Thus:

<?php
function f( $x = 4 ) { echo $x . "\\n"; }
f(); // prints 4
f( null ); // prints blank line
f( $y ); // $y undefined, prints blank line
?>

The utility of the optional argument feature is thus somewhat diminished.  Suppose you want to call the function f many times from function g, allowing the caller of g to specify if f should be called with a specific value or with its default value:

<?php
function f( $x = 4 ) {echo $x . "\\n"; }

// option 1: cut and paste the default value from f's interface into g's
function g( $x = 4 ) { f( $x ); f( $x ); }

// option 2: branch based on input to g
function g( $x = null ) { if ( !isset( $x ) ) { f(); f() } else { f( $x ); f( $x ); } }
?>

Both options suck.

The best approach, it seems to me, is to always use a sentinel like null as the default value of an optional argument.  This way, callers like g and g's clients have many options, and furthermore, callers always know how to omit arguments so they can omit one in the middle of the parameter list.

<?php
function f( $x = null ) { if ( !isset( $x ) ) $x = 4; echo $x . "\\n"; }

function
g( $x = null ) { f( $x ); f( $x ); }

f(); // prints 4
f( null ); // prints 4
f( $y ); // $y undefined, prints 4
g(); // prints 4 twice
g( null ); // prints 4 twice
g( 5 ); // prints 5 twice

?>
ksamvel at gmail dot com 07-Feb-2006 07:55
by default Classes constructor does not have any arguments. Using small trick with func_get_args() and other relative functions constructor becomes a function w/ args (tested in php 5.1.2). Check it out:

class A {
    public function __construct() {
        echo func_num_args() . "<br>";
        var_dump( func_get_args());
        echo "<br>";
    }
}

$oA = new A();
$oA = new A( 1, 2, 3, "txt");

Output:

0
array(0) { }
4
array(4) { [0]=> int(1) [1]=> int(2) [2]=> int(3) [3]=> string(3) "txt" }
Sergio Santana: ssantana at tlaloc dot imta dot mx 31-Oct-2005 02:59
PASSING A "VARIABLE-LENGTH ARGUMENT LIST OF REFERENCES" TO A FUNCTION
As of PHP 5, Call-time pass-by-reference has been deprecated, this represents no problem in most cases, since instead of calling a function like this:
   myfunction($arg1, &$arg2, &$arg3);

you can call it
   myfunction($arg1, $arg2, $arg3);

provided you have defined your function as
   function myfuncion($a1, &$a2, &$a3) { // so &$a2 and &$a3 are
                                                             // declared to be refs.
    ... <function-code>
   }

However, what happens if you wanted to pass an undefined number of references, i.e., something like:
   myfunction(&$arg1, &$arg2, ..., &$arg-n);?
This doesn't work in PHP 5 anymore.

In the following code I tried to amend this by using the
array() language-construct as the actual argument in the
call to the function.

<?php

 
function aa ($A) {
   
// This function increments each
    // "pseudo-argument" by 2s
   
foreach ($A as &$x) {
     
$x += 2;
    }
  }
 
 
$x = 1; $y = 2; $z = 3;
 
 
aa(array(&$x, &$y, &$z));
  echo
"--$x--$y--$z--\n";
 
// This will output:
  // --3--4--5--
?>

I hope this is useful.

Sergio.
grinslives13 at hotmail dot com~=s/i/ee/g 24-Sep-2005 10:55
Given that we have two coding styles:

#
# Code (A)
#
funtion foo_a (&$var)
{
    $var *= 2;
    return $var;
}
foo_a($a);

#
# Code (B)
#
function foo_b ($var)
{
    $var *= 2;
    return $var;
}
foo_b(&$a);

I personally wouldn't recommend (B) - I think it strange why php would support such a convention as it would have violated foo_b's design - its use would not do justice to its function prototype. And thinking about such use, I might have to think about copying all variables instead of working directly on them...

Coding that respects function prototypes strictly would, I believe, result in code that is more intuitive to read. Of course, in php <=4, not being able to use default values with references, we can't do this that we can do in C:

#
# optional return-value parameters
#
int foo_c (int var, int *ret)
{
    var *= 2;
    if (ret) *ret = var;
    return var;
}
foo_c(2, NULL);

Of course, since variables are "free" anyway, we can always get away with it by using dummy variables...

zlel
nate at natemurray dot com 30-Aug-2005 03:15
Of course you can fake a global variable for a default argument by something like this:
<?php
function self_url($text, $page, $per_page = NULL) {
 
$per_page = ($per_page == NULL) ? $GLOBALS['gPER_PAGE'] : $per_page; # setup a default value of per page
 
return sprintf("<a href=%s?page=%s&perpage=%s>%s</a>", $_SERVER["PHP_SELF"], $page, $per_page, $text);
}
?>
Angelina Bell 25-Jul-2005 12:40
It is so easy to create a constant that the php novice might do so accidently while attempting to call a function with no arguments.  For example:
<?php
function LogoutUser(){
// destroy the session, the cookie, and the session ID
 
blah blah blah;
  return
true;
}
function
SessionCheck(){
 
blah blah blah;
// check for session timeout
...
    if (
$timeout) LogoutUser// should be LogoutUser();
}
?>

OOPS!  I don't notice my typo, the SessionCheck function
doesn't work, and it takes me all afternoon to figure out why not!

<?php
LogoutUser
;
print
"new constant LogoutUser is " . LogoutUser;
?>
balint , at ./ atres &*( ath !# cx 30-Jun-2005 02:59
(in reply to benk at NOSPAM dot icarz dot com / 24-Jun-2005 04:21)
I could make use of this assignment, as below, to have a permanently existing, but changing data block (because it is used by many other classes), where the order or the refreshed contents are needed for the others: (DB init done by one, an other changed the DB, and thereafter all others need to use the other DB without creating new instances, or creating a log array in one, and we would like to append the new debug strings to the array, atmany places.)

class xyz {
    var argN = array();
    function xyz($argN) {
        $this->argN = &$argN;
    }
    function etc($text) {
        array_push($this->argN, $text);
    }
}
class abc {
    var argM = array();
    function abc($argM) {
        $this->argM = &$argM;
    }
    function etc($text) {
        array_push($this->argM, $text);
    }
}

$messages=array("one", "two");
$x = new xyz(&$messages);
$x->etc("test");

$a = new abc(&$messages);
$a->etc("tset");

...
csaba at alum dot mit dot edu 26-Jan-2005 04:58
Argument evaluation left to right means that you can save yourself a temporary variable in the example below whereas $current = $prior + ($prior=$current) is just the same as $current *= 2;

function Sum() { return array_sum(func_get_args()); }
function Fib($n,$current=1,$prior=0) {
    for (;--$n;) $current = Sum($prior,$prior=$current);
    return $current;
}

Csaba Gabor
PS.  You could, of course, just use array_sum(array(...)) in place of Sum(...)
heck AT fas DOT harvard DOT edu 24-Mar-2004 05:49
I have some functions that I'd like to be able to pass arguments two ways: Either as an argument list of variable length (e.g. func(1, 2, 3, 4)) or as an array (e.g., func(array(1,2,3,4)). Only the latter can be constructed on the fly (e.g., func($ar)), but the syntax of the former can be neater.

The way to do it is to begin the function as follows:
  $args = func_get_args();
  if (is_array ($args[0]))
    $args = $args[0];
Then one can just use $args as the list of arguments.
thesibster at hotmail dot com 30-Jun-2003 11:43
Call-time pass-by-ref arguments are deprecated and may not be supported later, so doing this:

----
function foo($str) {
    $str = "bar";
}

$mystr = "hello world";
foo(&$mystr);
----

will produce a warning when using the recommended php.ini file.  The way I ended up using for optional pass-by-ref args is to just pass an unused variable when you don't want to use the resulting parameter value:

----
function foo(&$str) {
    $str = "bar";
}

foo($_unused_);
----

Note that trying to pass a value of NULL will produce an error.
guillaume dot goutaudier at eurecom dot fr 19-Jul-2002 12:15
Concerning default values for arguments passed by reference:
I often use that trick:
func($ref=$defaultValue) {
    $ref = "new value";
}
func(&$var);
print($var) // echo "new value"

Setting $defaultValue to null enables you to write functions with optional arguments which, if given, are to be modified.
wls at wwco dot com 20-Nov-2001 11:29
Follow up to resource passing:

It appears that if you have defined the resource in the same file
as the function that uses it, you can get away with the global trick.

Here's the failure case:

  include "functions_doing_globals.php"
  $conn = openDatabaseConnection();
  invoke_function_doing_global_conn();

...that it fails.

Perhaps it's some strange scoping problem with include/require, or
globals trying to resolve before the variable is defined, rather
than at function execution.
rwillmann at nocomment dot sk 21-Jun-2001 03:05
There is no way how to deal with calling by reference when variable lengths argument list are passed.
<br>Only solutions is to use construction like this:<br>
function foo($args) {<br>
   ...
}

foo(array(&$first, &$second));

Above example pass by value a list of references to other variables :-)

It is courios, becouse when you call a function with arguments passed via &$parameter syntax, func_get_args returns array of copies :-(

rwi
artiebob at go dot com 25-Feb-2001 01:48
here is the code to pass a user defined function as an argument.  Just like in the usort method.

<?php
func2
("func1");
function
func1 ($arg){
        print (
"Hello $arg");       
}
function
func2 ($arg1){        
       
$arg1("World");  //Does the same thing as the next line
       
call_user_func ($arg1, "World");
}
?>
coop at better-mouse-trap dot com 09-Oct-2000 08:59
If you prefer to use named arguments to your functions (so you don't have to worry about the order of variable argument lists), you can do so PERL style with anonymous arrays:

<?php
function foo($args)
{
    print
"named_arg1 : " . $args["named_arg1"] . "\n";
    print
"named_arg2 : " . $args["named_arg2"] . "\n";
}

foo(array("named_arg1" => "arg1_value", "named_arg2" => "arg2_value"));
?>

will output:
named_arg1 : arg1_value
named_arg2 : arg2_value