International PHP Conference 2015

関数の引数

引数のリストにより関数へ情報を渡すことができます。 このリストは、カンマで区切られた式のリストです。 引数の評価は、左から右の順番で行われます。

PHP は、値渡し(デフォルト)、 参照渡しデフォルト引数値 をサポートしています。また、 可変長引数リスト もサポートしてます。

例1 関数に配列を渡す

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

引数の参照渡し

デフォルトで、関数の引数は値で渡されます。(このため、関数の内部で 引数の値を変更しても関数の外側では値は変化しません。)関数がその引 数を修正できるようにするには、その引数を参照渡しとする必要があり ます。

関数の引数を常に参照渡しとしたい場合には、関数定義において アンパサンド(&) を引数名の前に付加することができます。

例2 関数のパラメータの参照渡し

<?php
function add_some_extra(&$string)
{
    
$string .= 'and something extra.';
}
$str 'This is a string, ';
add_some_extra($str);
echo 
$str;    // 出力は 'This is a string, and something extra.' となります
?>

デフォルト引数値

関数は、スカラー引数に関して次のように C++ スタイルのデフォルト値を 定義することができます。

例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では、配列および特殊な型 NULL をデフォルト値とすることも可能です。 例えば、

例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");
?>

デフォルト値は、定数式である必要があり、 (例えば) 変数やクラスのメンバーであってはなりません。

引数のデフォルト値を使用する際には、デフォルト値を有する引数はデ フォルト値がない引数の右側に全てある必要があることに注意して下さ い。そうでない場合、意図したような動作が行われません。次の簡単な コードを見てみましょう。

例5 関数の引数のデフォルト値の 間違った使用法

<?php
function makeyogurt($type "acidophilus"$flavour)
{
    return 
"Making a bowl of $type $flavour.\n";
}
 
echo 
makeyogurt("raspberry");   // 期待通りには動作しません。
?>

上の例の出力は以下となります。

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 .

ここで、上の例を次のコードと比べてみましょう。

例6 関数の引数のデフォルト値の 正しい使用法

<?php
function makeyogurt($flavour$type "acidophilus")
{
    return 
"Making a bowl of $type $flavour.\n";
}
 
echo 
makeyogurt("raspberry");   // 期待通り動作します
?>

上の例の出力は以下となります。

Making a bowl of acidophilus raspberry.

注意: PHP 5以降では、リファレンス渡しの引数にもデフォルト値を指定できます。

型宣言

注意:

型宣言は、PHP 5 ではタイプヒンティングとも呼ばれていました。

型宣言を使うと、関数の呼び出し時にパラメータが特定の型であることを要求できるようになります。 指定した値が不正な型であった場合はエラーとなります。 PHP 5 では、このエラーは recoverable fatal error でした。 PHP 7 では、この場合に TypeError 例外をスローします。

型宣言を指定するには、型の名前をパラメータ名の前に追加します。 パラメータのデフォルト値が NULL である場合は、型宣言でも NULL 値を受け付けることができます。

有効な型

説明 利用可能な PHP の最低バージョン
クラス名 / インターフェイス名 パラメータは、指定したクラスやインターフェイスのインスタンスでなければいけません。 PHP 5.0.0
array パラメータは配列でなければいけません。 PHP 5.1.0
callable パラメータは callable でなければいけません。 PHP 5.4.0
bool パラメータは boolean 値でなければいけません。 PHP 7.0.0
float パラメータは float でなければいけません。 PHP 7.0.0
int パラメータは integer でなければいけません。 PHP 7.0.0
string パラメータは string でなければいけません。 PHP 7.0.0

例7 クラスの型宣言の基本例

<?php
class {}
class 
extends {}

// これは 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

例8 インターフェイスの型宣言の基本例

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

// これは 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

例9 Null を許可する型宣言

<?php
class {}

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

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

上の例の出力は以下となります。

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

強い型付け

デフォルトでは、間違った型を渡された場合でも、可能な限りは来されている型に変換します。 たとえば、string を想定している関数のパラメータに integer が渡された場合は、その値を string 型として受け取ります。

ファイル単位で厳密な型チェックを有効にすることもできます。 この場合は、宣言されたとおりの型でない限りは受け付けず、 TypeError をスローします。 ただし、float が指定されているところに integer を渡した場合だけは例外です。

厳密な型チェックを有効にするには、declare 文を用いて strict_types を宣言します。

警告

厳密な型チェックを有効にすると、 戻り値の型宣言 にも影響を及ぼします。

注意:

厳密な型チェックが適用されるのは、それを有効にしたファイル の中からの関数呼び出しだけです。 そのファイル内で宣言されている関数に適用されるわけではありません。 厳密な型チェックを有効にしていないファイルから、 厳密な型チェックを有効にしたファイル内で定義された関数を呼び出した場合は、 呼び出し元の設定 (弱い型チェック) が適用されて、自動的に型変換を行います。

注意:

厳密な型チェックはスカラー型宣言に対してのみ定義されるものであり、 PHP 7.0.0 以降でなければ使えません。そもそもスカラー型宣言が追加されたのが PHP 7.0.0 だからです。

例10 厳密な型チェック

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

例11 弱い型チェック

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

var_dump(sum(12));

// これらは integer 型として扱われます。出力例に注目!
var_dump(sum(1.52.5));
?>

上の例の出力は以下となります。

int(3)
int(3)

例12 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() 関数を使用します。

PHP 5.6 以降における ...

PHP 5.6 以降では、引数リストに ... トークンを含めることで、 その関数が可変長の引数を受け取ることを示せます。 引数は、指定した変数に配列として渡されます。次の例を参照ください。

例13 ... を使った、可変長引数へのアクセス

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

echo 
sum(1234);
?>

上の例の出力は以下となります。

10

関数を呼び出すときに ... を使うと、 配列変数や Traversable クラスを引数リストに含めることができます。

例14 引数での ... の使用例

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

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

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

上の例の出力は以下となります。

3
3

通常の引数を、... の前に指定することもできます。 この場合は、通常の引数リストにマッチしなかったのこりの引数が ... による配列に追加されます。

... トークンの前に、 タイプヒント を付加することもできます。 タイプヒントがある場合、... が取り込むすべての引数はそのヒントに従わなければいけません。

例15 タイプヒントつきの可変長引数

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

// これは失敗します。null は DateInterval オブジェクトではないからです。
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

可変長引数の 参照渡し もできます。その場合は、... の前にアンパサンド (&) を付加します。

古いバージョンの PHP

可変長引数に関して特別な構文は必要としません。しかし、関数の引数にアクセスするには func_num_args()func_get_arg() および func_get_args() といった関数を使う必要があります。

先ほどの最初の例を、PHP 5.5 以前のバージョンで実装すると、以下のようになります。

例16 可変長引数へのアクセス (PHP 5.5 以前)

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

echo 
sum(1234);
?>

上の例の出力は以下となります。

10

add a note add a note

User Contributed Notes 37 notes

up
3
php at richardneill dot org
5 months ago
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".
*/
?>
up
21
carlos at wfmh dot org dot pl dot REMOVE dot COM
5 years ago
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).
up
10
Sergio Santana: ssantana at tlaloc dot imta dot mx
9 years ago
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.
up
2
lucas dot ekrause at gmail dot com
1 year ago
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());}}
?>
up
8
herenvardoREMOVEatSTUFFgmailINdotCAPScom
6 years ago
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.
up
5
Horst Schirmeier
1 year ago
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; }).
up
3
ravenswd at gmail dot com
2 years ago
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"
}
?>
up
5
thesibster at hotmail dot com
12 years ago
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.
up
6
rburnap at intelligent dash imaging dot com
5 years ago
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
up
7
conciseusa at yahoo[nospammm] dot com
8 years ago
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
up
7
John
8 years ago
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)
up
6
allankelly at gmail dot com
6 years ago
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>";
}
?>
up
3
jcaplan at bogus dot amazon dot com
9 years ago
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

?>
up
4
mracky at pacbell dot net
5 years ago
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
up
3
wls at wwco dot com
13 years ago
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.
up
2
aasasdasdf at yandex dot ru
1 year ago
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)
up
4
ksamvel at gmail dot com
9 years ago
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" }
up
2
Don dot hosek at gmail dot com
7 years ago
Actually the use of class or global constants does buy us something. It helps enforce the DRY (don't repeat yourself) principle.
up
2
pigiman at gmail dot com
5 years ago
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
up
1
nate at natemurray dot com
10 years ago
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);
}
?>
up
1
guillaume dot goutaudier at eurecom dot fr
13 years ago
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.
up
1
keuleu at hotmail dot com
8 years ago
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:
*/
?>
up
1
artiebob at go dot com
14 years ago
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");
}
?>
up
1
rwillmann at nocomment dot sk
14 years ago
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
up
1
coop at better-mouse-trap dot com
14 years ago
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
up
0
d_maley at hotmail dot com
6 days ago
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
up
-1
pdenny at magmic dot com
8 years ago
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)
up
-2
grinslives13 at hotmail dot com~=s/i/ee/g
9 years ago
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
up
-2
heck AT fas DOT harvard DOT edu
11 years ago
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.
up
-2
csaba at alum dot mit dot edu
10 years ago
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(...)
up
-3
jacob at jacobweber dot com
4 years ago
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
?>
up
-3
Angelina Bell
10 years ago
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;
?>
up
-2
balint , at ./ atres &*( ath !# cx
10 years ago
(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");

...
up
-3
post at auge8472 dot de
2 years ago
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
up
-3
rich at richware dot net
3 months ago
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/>';
    }
up
-7
david at petshelter dot net
14 years ago
With reference to the note about extract() by dietricha@subpop.com:

He is correct and this is great!  What he does not say explicitly is that the extracted variable names have the scope of the function, not the global namespace.  (This is the appropriate behavior IMO.)  If for some reason you want the extracted variables to be visible in the global namespace, you must declare them 'global' inside the function.
up
-8
almasy at axisdata dot com
15 years ago
Re: Passing By Reference Inside A Class

Passing arguments by reference does work inside a class.  When you do:

    $this->testVar = $ref;

inside setTestVar(), you're copying by value instead of copying by reference.  I think what you want there is this:

    $this->testVar = &$ref;

Which is the new "assign by reference" syntax that was added in PHP4.
To Top