What is the purpose of the question marks before type declaration in PHP7 (?string or ?int)?
What is a Nullable Type?
Introduced in PHP 7.1,
Type declarations for parameters and return values can now be marked as nullable by prefixing the type name with a question mark. This signifies that as well as the specified type, NULL can be passed as an argument, or returned as a value, respectively.
In parameters
function test(?string $parameter1, string $parameter2) {
var_dump($parameter1, $parameter2);
}
test("foo", "bar");
test(null, "foo");
test("foo", null); // Uncaught TypeError: Argument 2 passed to test() must be of the type string, null given,
With variadic arguments
In this example, you can pass null
or string
parameters :
function acceptOnlyStrings(string ...$parameters) { }
function acceptStringsAndNull(?string ...$parameters) { }
acceptOnlyStrings('foo', null, 'baz'); // Uncaught TypeError: Argument #2 must be of type string, null given
acceptStringsAndNull('foo', null, 'baz'); // OK
Return type
The return type of a function can also be a nullable type, and allows to return null
or the specified type.
function error_func(): int {
return null ; // Uncaught TypeError: Return value must be of the type integer
}
function valid_func(): ?int {
return null ; // OK
}
function valid_int_func(): ?int {
return 2 ; // OK
}
Property type (as of PHP 7.4)
The type of a property can be a nullable type.
class Foo
{
private object $foo = null; // ERROR : cannot be null
private ?object $bar = null; // OK : can be null (nullable type)
private object $baz; // OK : uninitialized value
}
See also :
Nullable union types (as of PHP 8.0)
As of PHP 8, "?T
notation is considered a shorthand for the common case of T|null
"
class Foo
{
private ?object $bar = null; // as of PHP 7.1+
private object|null $baz = null; // as of PHP 8.0
}
Error
In case of the running PHP version is lower than PHP 7.1, a syntax error is thrown:
syntax error, unexpected '?', expecting variable (T_VARIABLE)
The ?
operator should be removed.
PHP 7.1+
function foo(?int $value) { }
PHP 7.0 or lower
/**
* @var int|null
*/
function foo($value) { }
References
As of PHP 7.1: Nullable type :
As of PHP 7.4: Class properties type declarations.
As of PHP 8.0: Nullable Union Type
What does question mark (?) before type declaration means in php (?int)
It's called Nullable types
.
Which defines ?int
as either int
or null
.
Type declarations for parameters and return values can now be marked as nullable by prefixing the type name with a question mark. This signifies that as well as the specified type, NULL can be passed as an argument, or returned as a value, respectively.
Example :
function nullOrInt(?int $arg){
var_dump($arg);
}
nullOrInt(100);
nullOrInt(null);
function nullOrInt
will accept both null and int.
Ref: http://php.net/manual/en/migration71.new-features.php
Null check on type hinting php
This means that the argument is also allowed to be null: Nullable Types
PHP: How do I fix this type hinting error?
From the manual
Typed pass-by-reference Parameters
Declared types of reference parameters are checked on function entry, but not when the function returns, so after the function had returned, the argument's type may have changed.
Given you are immediately assigning a new value to $output
, its type declaration is irrelevant. Either omit the type declaration or mark it nullable
function foo(int $one, int $two, ?int &$output): void
{
$output = $one + $two;
}
https://3v4l.org/j91DG
Of course, this type of pattern is convoluted and makes no sense over something as simple as
function foo(int $one, int $two): int
{
return $one + $two;
}
What does :? after a method means in PHP?
This is a new feature as of PHP 7.1. See the explanation here
Type declarations for parameters and return values can now be marked as nullable by prefixing the type name with a question mark. This signifies that as well as the specified type, NULL can be passed as an argument, or returned as a value, respectively.
This means the expected output of your function will be either an Instance of the class Article
or it is NULL
.
What does typehint ?string mean
Since PHP 7.1 nullable return types or nullable type hinting with a question mark exists. Since PHP 8.0 union types are available. If you want to write null|string
you can do this since PHP 8.0. This notation expresses the same as ?string
.
Which notation you use is up to your personal taste. Since the notation with the question mark is shorter, I personally would prefer this notation.
Is it possible to type hint more than one type?
Academically, this is called a type union.
Union types in PHP
You can cheat by creating interfaces, parent types, etc, as mentioned in other answers, but what's the point, apart for adding complexity and LoCs to your project? Plus, that can't work for scalar types as you can't extend/implement a scalar type.
Instead of making the code more readable, you'll get the opposite. Except if those classes/interfaces already existed and they are here because of OOP, not to solve a type hinting problem.
Workarounds
The canonical answer in PHP is... well, just don't put a type hint. The language was not thought to have a complex and powerful type system, and trying to workaround the flaws of the language is not a good answer.
Instead, document your function properly:
/**
* Description of what the function does.
*
* @param User|File $multiTypeArgument Description of the argument.
*
* @return string[] Description of the function's return value.
*/
function myFunction($multiTypeArgument)
{
This will at least bring IDE support for autocompletion and static code analysis. Well enough when working on a private project, website, etc.
When designing a public API (a PHP library, etc), sometimes you may want to be more defensive about API consumers' inputs.
Then @tilz0R answer is the way to go:
function log($message) {
if (!is_string($message) && !$message instanceof Message) {
throw new \InvalidArgumentException('$message must be a string or a Message object.');
}
// code ...
}
The day PHP (almost) had union types
The 14th of February 2015, the Union Types PHP RFC was proposed for PHP 7.1. After discussion and vote, it's been rejected, 18 "no" against 11 "yes".
If the RFC had been accepted, PHP would have had union types exactly the way you've shown (User|File
).
The RFC had some flaws, but the main reason for why it's been rejected is that the mainteners voters are quite resistive to change especially when it's about type strictness and other programming paradigms (ex. "why would we need type unions when the default takes all types of values" and "that's not good for performance").
Related Topics
Function Ereg_Replace() Is Deprecated - How to Clear This Bug
Send Email with Attachment Using PHP
Pdo Prepared Statement Fetch() Returning Double Results
Difference Between Break and Continue in PHP
Determine in PHP Script If Connected to Internet
PHP Form Token Usage and Handling
How to Create a Facade Class with Laravel
#1193 - Unknown System Variable 'Lc_Messages' When Trying to Login to PHPmyadmin
PHP - Merge Two Arrays (Same-Length) into One Associative
Cross Domain Ajax Request with Jquery/Php
Session Lost After Page Redirect in PHP
MySQL Encryption/Storing Sensitive Data,
Is Is Bad Practice to Use Array_Walk with MySQLi_Real_Escape_String
Accessing Files Relative to Bundle in Symfony2
Increasing PHP Memory_Limit. at What Point Does It Become Insane