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

Exemples

Exemple #7 Déclaration basique de type de classe

<?phpclass C {}class D extends C {}

// Ceci n'étend pas Cclass E {}

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

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

L'exemple ci-dessus va afficher :

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

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

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

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

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

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.

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.

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.

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.

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

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

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

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

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:

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)

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.:<?phpfunction foo(?string $a, string $b) {}?>

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.

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:

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:

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

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

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:

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.

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