|
Function argumentsInformation may be passed to functions via the argument list, which is a comma-delimited list of expressions. PHP supports passing arguments by value (the default), passing by reference, and default argument values. Variable-length argument lists are supported only in PHP 4 and later; see Variable-length argument lists and the function references for func_num_args(), func_get_arg(), and func_get_args() for more information. A similar effect can be achieved in PHP 3 by passing an array of arguments to a function: Example 8.5. Passing arrays to functions<?php By default, function arguments are passed by value (so that if you change the value of the argument within the function, it does not get changed outside of the function). If you wish to allow a function to modify its arguments, you must pass them by reference. If you want an argument to a function to always be passed by reference, you can prepend an ampersand (&) to the argument name in the function definition: Example 8.6. Passing function parameters by reference<?php A function may define C++-style default values for scalar arguments as follows: Example 8.7. Use of default parameters in functions<?php The output from the above snippet is: Making a cup of cappuccino. Also PHP allows you to use arrays and special type NULL as default values, for example: Example 8.8. Using non-scalar types as default values<?php The default value must be a constant expression, not (for example) a variable, a class member or a function call. 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. Consider the following code snippet: Example 8.9. Incorrect usage of default function arguments<?php The output of the above example is: warning: missing argument 2 in call to makeyogurt() in now, compare the above with this: Example 8.10. Correct usage of default function arguments<?php The output of this example is: Making a bowl of acidophilus raspberry.
Note:
As of PHP 5, default values may be passed by reference. PHP 4 and above has support for variable-length argument lists in user-defined functions. This is really quite easy, using the func_num_args(), func_get_arg(), and func_get_args() functions. No special syntax is required, and argument lists may still be explicitly provided with function definitions and will behave as normal. Code Examples / Notes » functions.arguments21-apr-2000 10:45
You may pass any number of extra parameters to a function, regardless of the prototyping. In addition, the arguments passed to a function will be available via the variable names defined in the function prototype, as well as via the func_get_arg() and func_get_args() functions. For example: function printme ($arg) { for ($ndx = 0; $ndx < $num_args; ++$ndx) $output .= func_get_arg ($ndx); print $output; } printme ("one ", "two"); # This prints "one two". This behavior is useful for setting default values for function arguments and for ensuring that a certain number of arguments get passed to a function. conciseusa
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 david
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. keeper
Whem arguments are passed by reference, default values won´t work.
john
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) benk
This isn't necessarily the right place to store this piece of information, but I discovered a neat feature of the 'by reference' operator (&). You can use this assignment operator to assign a pointer to another variable. This makes it possible to update BOTH varaibles and have the value change in the other. I have not yet explored scope of this test, but here is a simple test that I ran on PHP 4.3.9 with the following results: $abc = "Test"; $def = ""; print("ABC = $abc\tDEF = $def\n"); // ABC = Test DEF = $def = &$abc; print("ABC = $abc\tDEF = $def\n"); // ABC = Test DEF = Test $abc = "test2"; print("ABC = $abc\tDEF = $def\n"); // ABC = test2 DEF = test2 $def = "nextval"; print("ABC = $abc\tDEF = $def\n"); // ABC = nextval DEF = nextval unset($def); print("ABC = $abc\tDEF = $def\n"); // ABC = nextval DEF = $def = "yet another value"; print("ABC = $abc\tDEF = $def\n"); // ABC = nextval DEF = yet another value rwillmann
There is no way how to deal with calling by reference when variable lengths argument list are passed. Only solutions is to use construction like this: function foo($args) { ... } 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 dmb27
The first comment should use func_get_arg(0) and func_get_arg(1) to refer to the 2 parameters (and not func_get_arg(2) ). func_get_arg() starts counting at 0, so the first parameter is func_get_arg(0) and the second is func_get_arg(1)
jbarnett
The documentation says, "The default value must be a constant expression, not (for example) a variable, a class member or a function call." Class constants (and presumably global constants) can be used: <?php class Foo { const BAR = "constant value"; public function myMethod($arg = self::BAR) { echo $arg; // IT WORKS! } } ?> almasy
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. sergio santana: ssantana
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. ak
One interesting thing I've noticed: function foo() { // accepts any number of arguments bar() } function bar($x,$y) { // same print("$x $y"); } foo("one","two); OUPUT: "one two" That is, PHP will automatically pass all the variables passed to foo() into bar() if you don't pass them explicitly. I'm not sure how far this extends (i.e. if you pass just one variable, will the rest still get tacked on? etc), but it's interesting, and undocumented. nate
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); } ?> adrian
Note that passing by reference doesn't speed up your php script. PHP is smart enough not to simply copy data every time the language requires it. Rahter, PHP uses a reference and waits until the copy (a copied variable or a copy used in a function) is actually used as a copy and creates one then.
pdenny
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) mjohnston
not only do default values not work with passing by reference, but you can't pass NULL as a parameter that is expected to be a reference, and passing too few parameters to a function causes a warning.
marvinalone
Nice to know is this: If you call a function giving an unset variable, it will be unset in the function. Consider this: function my_test ($var) { if (isset ($var)) echo ("set"); } my_test ($unused); This will _not_ echo "set", regardless of the variable being passed by value or by reference. (If my newlines are messed up, sorry, this seems to be a konqueror problem) angelina bell
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; ?> jim
It is also possible to force a parameter type using this syntax. I couldn't see it in the documentation. function foo(myclass par) { } jcaplan
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 ?> coop
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: 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 dietricha
if you compiled with "--enable-track-vars" then an easy way to get variable function args is to use extract(). $args = array("color" = "blue","number" = 3); function my_func($args){ extract($args); echo $color; echo $number; } the above strategy makes it real easy to globalize form data within functions, or to pass form data arrays to functions: <input type="text" name="test[color]" value="blue"> etc, etc. Then in your function, pass $test to extract() to turn the array data into global vars. or function my_func($HTTP_POST_VARS){ extract($HTTP_POST_VARS); // use all your vars by name! } keuleu
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: */ ?> duncanmadcow
I have tried the example given by ak@avatartech.com it did not work I use php 4.0.6 on windows 98 I do think that it is good that there is no automatic parameter passing, thus it would force people to do good programming practie heck
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. alex
I found this useful: You can call a function by using the value of a string. function test() { echo "hello world"; } $string = "test"; $string(); would output "hello world" artiebob
here is the code to pass a user defined function as an argument. Just like in the usort method. 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"); } bostjan dot skufca
have function function foo($bar=3) { if (!isset($bar)) { echo "I'm not set to my default value"; } and if you do foo($some_unset_variable); the $bar variable does not adopt default value (3) as one might expect but it is not set. grinslives13
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 trosos
Function arguments are evaluated from left to right.
wls
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. korba
Don't try to pass func_get_arg() as an argument of the other function. So: function foo() { foo2(func_get_arg(0)); } won't work. t dot orf
concerning rbronosky@mac.com 11-May-2001 06:17: You can include the variable name in the output if you simply pass that name instead of the value: function show($arrayName) { global $$arrayName; echo("<pre>\n$arrayName == "); print_r($$arrayName); echo "</pre>"; } show('myArray'); guillaume dot goutaudier
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. thesibster
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. ksamvel
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() . " "; var_dump( func_get_args()); echo " "; } } $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" } csaba
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(...) bishop
A tiny clarification on the notes of "keeper at odi dot com dot br", et. al. Functions explicitly prototyped with formal parameters passed by reference can't have default values. However, functions prototyped to assign default values to formal parameters may be passed references. For example, this is a parse error: function foo(&$bar = null) { // formal parameters as references can't have default values $bar = 242; } While this is perfectly legal (and probably what you want, mostly): function foo($bar = null) { $bar = 242; } foo(); // valid call, no warnings about missing args foo(&$x); // valid call, post $x == 242 jesdisciple @t gmail -dot- com
@ jbarnett at flowershopnetwork dot com: Yes, but that doesn't get us anywhere; you could just as well have said: myMethod($arg = "constant value") Class constants must have constant values, as well. http://www.php.net/manual/en/language.oop5.constants.php balint ,
(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"); ... |