PHP 8.0: New mixed
pseudo type
mixed
is a pseudo type added in PHP 8 that conveys the type of the parameter/return/property can be of any type. mixed
type includes all scalar types in PHP, null
, all class objects, callable
, and even resource
.
mixed
is equivalent to a Union Type of:
string|int|float|bool|null|array|object|callable|resource
With mixed
, it is now possible to declare mixed
as the type when the parameters, returns, and class properties can be of any type.
class Example {
public mixed $exampleProperty;
public function foo(mixed $foo): mixed {}
}
mixed
is a pseudo type
mixed
represents any type PHP can handle, and thus you cannot cast a variable to mixed
because it simply doesn't make sense.
$foo = (mixed) $bar;
Further, there is no is_mixed()
function for the same reasons.
gettype()
and get_debug_type()
functions will never return mixed
as the type of a variable either.
mixed
in union with other types
Because mixed
represents all types, mixed
cannot be used in union with other types:
function (mixed|FooClass $bar): int|mixed {}
Both union types above are not allowed, and will result in a fatal error:
Fatal error: Type mixed can only be used as a standalone type in ... on line ...
mixed
is assumed when no type is declared
When a function parameter or a class property has no explicit type declared, the type is now assumed to be mixed
.
Be mindful when you add
mixed
type to all your existing code; PHP 8 has Union Types that might be a better fit because Union Types allow you to be more specific.
For return types, lack of an explicit return type is equal to mixed|void
.
However, note that you cannot declare
mixed|void
as a return type becausemixed
is not allowed in a Union Type.
Type variance
When a class method, return type, or a property type is overridden by a sub-class, Liskov Substitution Principle is respected.
Contravariance: mixed
parameters types
Function parameter types can be "widened" at a child class or an interface implementation because the widened type still fulfills the contract of the interface/parent class. This means child class parameters can declare a type with a Union Type that includes more types, or a class name that is a parent of the current class.
When a parameter type is declared as mixed
, this practically prevents further contravariance because mixed
includes all types PHP works with. If possible, always opt for more specific types because once you mark a parameter type as mixed
in a public API, all child classes must be capable to deal with mixed types.
Covariance: mixed
return types
If a parent class method has declared a return type other than mixed
, child classes will not be allowed to declare mixed
because it widens the return type scope, thus breaking LSP.
class A {
public function foo(): mixed {}
}
class B extends A{
public function foo(): void {}
}
The above will result in a fatal error:
Fatal error: Declaration of B::foo(): void must be compatible with A::foo(): mixed
This is because mixed
does not include void
type. If a return type is not explicitly declared, it is assumed to be mixed|void
.
All following declarations are allowed:
class A {
public function foo() {}
public function bar() {}
public function baz(): mixed {}
}
class B extends A{
public function foo(): mixed {}
public function bar(): void {}
public function baz(): string {}
}
B::foo
: Allowed: Narrows down the assumedmixed|void
return type ofA::foo
.B::bar
: Allowed: Narrows down the assumedmixed|void
return type ofA::bar
.B::baz
: Allowed: Narrows down the declaredmixed
type.
Invariance: mixed
property types
If a property type is declared as mixed
, this type cannot be omitted or changed at all.
Usage with void
PHP supports void
pseudo return type to indicate that the function will not return anything. This is equivalent to lack of a return
statement, or return;
expression without setting an explicit value.
void
type and mixed
cannot be in a union. Further mixed
does not include void
.
Nullable mixed
types
It is not allowed to declare mixed
type as nullable because mixed
includes null
.
All of the following declarations are not allowed:
function foo(mixed|null $foo) {}
function foo(?mixed $foo) {}
function foo($foo): mixed|null {}
function foo($foo): ?mixed {}
All declarations above will raise a fatal error:
Fatal error: Type mixed can only be used as a standalone type in ... on line ...
Practical Usage
Many PHP internal functions accept various types, which can now be declared with the mixed
type. However, for user-land functions, it is often better to use a specific type or a Union Type.
Functions such var_dump
or get_debug_type()
can declare its parameters as mixed
because these functions accept any type by definition.
If you declare a parameter/return type/class property as mixed
type, be mindful that mixed
includes types such resource
and callable
, which are not easily stored, serialized, sanitized, or displayed.
Most user-land functions that need to "accept anything", such as logging functions are better off with a Union Type such as string|int|float|bool|null|object|array
.
Backwards compatibility
mixed
is soft-reserved since PHP 7. Until PHP 8, it is technically possible to declare a class with name mixed
, and it will not raise any errors, warnings, or notices. PHPDoc standard widely used mixed
as a type declaration, so it is highly unlikely that even the wildest code base out there declares a class with name mixed
.
Attempting to declare a class with name mixed
in PHP 8 results the following error:
Fatal error: Cannot use 'mixed' as class name as it is reserved in ... on line ...
Polyfill
It is not possible to polyfill this functionality because it's an internal type. If you use mixed
type anywhere in your code, be sure that it will always run on a PHP 8+ platform.