I'm on PHP 8.2.1. The following type hints work fine:
function abc(): ?string
function abc(): ?array
function abc(): string|array
...but a nullable union doesn't:
function abc(): ?string|array
>>> ParseError: syntax error, unexpected token "|", expecting "{"
Is there any workaround?
Is there any workaround?
the so called nullable type in PHP (since 7.1) was an early way to allow to attribute allowing null as well to a single return type to laxen the rules. it was deemed useful when PHP started with return types as only a single type was allowed to be typed and returning null as well a common scenario.
function abc(): ?string
function abc(): ?array
since version 8.0 PHP has union types, that is with the pipe symbol ("|"), shown in your third definition:
function abc(): string|array
you could however likewise use union types when upgrading the earlier code to union types:
function abc(): null|string
function abc(): null|array
so as workaround, perhaps the nullable type is better classified as, and then it may become more clear that the union type of all three is what you're looking for (and not a workaround, at least in my book and IIUC):
function abc(): null|string|array
the nullable type notation with the question mark symbol ("?") survives in code-bases because it is much shorter and the usage is common - but incompatible with the pipe-notation of union types.
it may also have a bit of a renaissance with the release of PHP 8.4 as it deprecates using null as default value for a parameter given the parameters type does not include null. adding the type as an attribute to a parameter is supported since PHP version 5 for array and classes.
The ?Foo syntax is considered a short-hand for the union type null|Foo (or Foo|null). It exists both because it was added before Union Types, and because it is a common case where a short-hand seems useful.
So in your example, all of these are valid:
function abc(): ?string {}
function abc(): ?array {}
function abc(): string|array {}
function abc(): null|string {}
function abc(): null|array {}
function abc(): null|string|array {}
function abc(): string|null {}
function abc(): array|null {}
function abc(): string|array|null {}
The short-hand can't be mixed with the full syntax, so these are not valid:
function abc(): ?string|array {}
function abc(): ?(string|array) {}
function abc(): ?string|?array {}
The design reasoning for this can be found in the RFC which introduced Union Types to PHP:
The null type is supported as part of unions, such that
T1|T2|nullcan be used to create a nullable union. The existing?Tnotation is considered a shorthand for the common case ofT|null.An earlier version of this RFC proposed to use
?(T1|T2)for nullable union types instead, to avoid having two ways of expressing nullability in PHP. However, this notation is both rather awkward syntactically, and differs from the well-establishedT1|T2|nullsyntax used by phpdoc comments. The discussion feedback was overwhelmingly in favor of supporting theT1|T2|nullnotation.
?Tremains valid syntax that denotes the same type asT|null. It is neither discouraged nor deprecated, and there are no plans to deprecate it in the future. It is merely a shorthand alias for a particularly common union type.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With