Srdjan Pazin
Srdjan Pazin

Reputation: 158

PHP - If a function parameter has a default value of null, should its type be declared as nullable?

Is it a best practice to mark as nullable (?string) the type of parameters that have a default value of null, given that the parameter is always passed as a string, for example (or some other non null value, it doesn't matter)? The default value of null is only specified to make the parameter optional.

function example(?string $param = null) {
    // Function logic here
}

The type declaration string $param is just fine since the parameter is always passed as a string, but since it has a default value of null, the type declaration perhaps doesn't accurately indicate the types that the parameter can have inside the function. So would the declaration ?string $param (or null|string $param) be more appropriate?

Upvotes: 3

Views: 2198

Answers (1)

Jakumi
Jakumi

Reputation: 8374

TL;DR: make a parameter type hint nullable if null is a meaningful value. (i.e. if it should be used in cases other than omission)


It's practically (and technically?) identical, i.e. function will accept an explicit null, even if the parameter is "not nullable" but has null as its default value.

However, the null default value makes it, as you already mentioned, an optional parameter (in that it can be omitted).

I have constructed this very bad design example to make a point:

abstract class SomeCommand {
  function setParameter(string $parameter = '');
  function run(); 
  function runWithParameter(string $parameter = null); // version 1
  function runWithParameter(?string $parameter = null); // version 2
}

Assume that you can set a default parameter for the command, which is always a string. Let's look at the versions of runWithParameter:

  • Version 1, IMHO, says, you can provide an override value for the parameter, but you can omit the parameter to keep the default.
  • Version 2, IMHO, says, you can provide an override and explicitly providing null might make a difference! but you can omit it.

Please note, that in version 1 and 2 BOTH, you can distinguish between the parameter being omitted or null being provided. Via func_get_args() this will produce [NULL] and [] respectively ($parameter is null in both cases, though). IMHO, it is a very BAD idea to rely on this difference/distinction!

However, I think there is a semantic difference: If you want the function to accept a meaningful null (besides "omission"), make the type hint nullable (?string), and if you want the function to only accept string, but it may be omitted, use = null.

This way, you can hopefully communicate, that a parameter given as null is meaningful or just used for omission, especially, if the function has more parameters.

(Corollary: if you want the parameter to always be provided, remove the default value, obviously, this can make sense to force the caller to make a conscious choice. Please beware, that an omitted or nullable parameter might be an indicator for two functions being forced into one, which, depending on the function complexity might be a code smell)

update

Since @shingo commented, that version 1 is not recommended: This concerns using = null to make a parameter nullable, i.e. like setParent($parent) in a tree. Here setParent(Node $parent = null) would work but would also be bad. Better: setParent(?Node $parent), this makes the parameter non-optional and also clearly communicates the type the parent can have.

Upvotes: 4

Related Questions