Making arguments be passed by reference

By default, function arguments are passed by value (so that if
the value of the argument within the function is changed, it does
not get changed outside of the function). To allow a function to modify its
arguments, they must be passed by reference.

To have an argument to a function always passed by reference, prepend an
ampersand (&) to the argument name in the function definition:

Notă:
As of PHP 5, arguments that are passed by reference may have a default value.

Scalar Type Declaration

Notă:

Type declaration is also known as Type Hinting.

PHP 7 introduces scalar type declaration. Functions are now able to force parameters
to be string, int, float or bool.
By default all PHP Files are in weakly typed mode.
To enable strict type checking, declare(strict_types=1)
directive must be the first
statement in the file. strict_types has two options, 1 for strict type
checking and 0 for weak type checking. This only affects the file this is stated in and not
files either included in this file or other files that include this file.
Whether or not the function being called was declared in a file that uses strict or weak
type checking is irrelevant. The type checking mode depends on the file where the function is called from.

Example #7 Scalar Type Declaration examples

<?phpdeclare(strict_types=1); // Fatal error if this is not the first statementinclude "foo.php";

Type Error

var_dump($e->getmessage()); // "Argument 1 passed to show() must be of the type // integer, string given, called in %s on line %d"}?>

<?php declare(strict_types=1);

function show(int $intNum){ return $a;}

show("1"); // Fatal Error

?>

Variable-length argument lists

PHP has support for variable-length argument lists in
user-defined functions. This is implemented using the
... token in PHP 5.6 and later, and using the
func_num_args(),
func_get_arg(), and
func_get_args() functions in PHP 5.5 and earlier.

... 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:

User Contributed Notes 36 notes

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).

PASSING A "VARIABLE-LENGTH ARGUMENT LIST OF REFERENCES" TO A FUNCTIONAs 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.

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.

<?phpfunction 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:*/?>

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; }).

// 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.

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:

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:

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:

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.

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).

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:

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)

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".*/?>

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:

"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:

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:<?phpfunction LogoutUser(){// destroy the session, the cookie, and the session IDblah 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 functiondoesn't work, and it takes me all afternoon to figure out why not!

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.

(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.)

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.