What is the difference between ?int $number and int $number = null?

If the language were designed today, int $var = null would probably be an error, and should really be written ?int $var = null. The two parts mean different things:

  • The ? indicates that null is a valid value for that parameter.
  • The = null indicates that null is the default if the parameter is not passed.

However, before the ?type syntax was introduced, there was a special case in the language: if null is given as the default for a parameter, then it is legal to pass null to that parameter, even if the type declaration would otherwise prevent it.


The difference is how you can call the function:

// public function test(?int $var)
$foo->test("x");    // does not work (Argument 1 passed to Foo::test() must be of the type int or null, string given)
$foo->test(123);    // works
$foo->test(null);   // works
$foo->test();       // does not work (Too few arguments to function Foo::test(), 0 passed)

// public function test(int $var = null)
$foo->test("x");    // does not work (Argument 1 passed to Foo::test() must be of the type int or null, string given)
$foo->test(123);    // works
$foo->test(null);   // works
$foo->test();       // works

The difference is that you cannot call the function as ->test() using the first syntax.


It is important to distinguish between the two language features being discussed here, that is, type declarations and default argument values.

The first function is only using type declarations, this means that the input argument has to be of the type int or NULL.

The second function is using both type declarations and default argument values, this means that the argument has to be of the type int or NULL but if omitted it will default to NULL.

Take your first function, if you simply called test() without passing anything to it, you'd get:

PHP Fatal error: Uncaught ArgumentCountError: Too few arguments to function test() [...]

which is correct as the function expects either int or NULL but got neither whereas for the second, as you have defined the argument with a default value, it would run without errors.

Code

function test(?int $var) {
  var_dump($var);
}

function test2(int $var = null) {
  var_dump($var);
}

test(1); // fine
test(); // error
test2(1); // fine
test2(); // fine

As far as performance goes, the difference is probably negligible, nothing significant enough that would be a cause for concern.

Live Example

Repl

Tags:

Php