mixed  — это псевдотип, добавленный в PHP 8, который указывает, что параметр, возвращаемое значение или свойство могут иметь любой тип. Тип  mixed  включает в себя все скалярные типы PHP,  null , все объекты классов,  callable  и даже  resource . 

 mixed  эквивалентен Union-типу (типу пересечения/объединения) из:

string|int|float|bool|null|array|object|callable|resource 

С появлением  mixed  теперь можно указывать  mixed  в качестве типа, когда параметры, возвращаемые значения и свойства классов могут быть абсолютно любого типа.

class Example {
    public mixed $exampleProperty;
    public function foo(mixed $foo): mixed {}
} 

 mixed  — это псевдотип 

 mixed  представляет любой тип, с которым может работать PHP, поэтому вы не можете привести переменную к  mixed  — в этом просто нет смысла. 

$foo = (mixed) $bar; 

Кроме того, по тем же причинам функции  is_mixed()  не существует. 

Функции  gettype()  и  get_debug_type() также никогда не вернут  mixed  в качестве типа переменной. 

 mixed  в объединении с другими типами 

Поскольку  mixed  представляет все типы,  mixed  нельзя использовать в union-типах с другими типами:

function (mixed|FooClass $bar): int|mixed {} 

Оба указанных выше union-типа недопустимы и приведут к фатальной ошибке:

Fatal error: Type mixed can only be used as a standalone type in ... on line ... 

 mixed  подразумевается, если тип не объявлен 

Если у  параметра функции или  свойства класса не объявлен явный тип, теперь предполагается, что его тип —  mixed . 

Будьте внимательны при добавлении типа  mixed  во весь существующий код: в PHP 8 появились Union-типы, которые могут подойти лучше, поскольку позволяют быть более точными.

Что касается  возвращаемых типов, отсутствие явно указанного возвращаемого типа эквивалентно  mixed|void . 

Однако учтите, что вы не можете объявить  mixed|void  в качестве возвращаемого типа, поскольку  mixed  запрещен в Union-типах.

Вариантность типов 

Когда метод класса, возвращаемый тип или тип свойства переопределяются подклассом, соблюдается принцип подстановки Барбары Лисков (LSP).

Контравариантность: типы параметров  mixed  

Типы параметров функций могут быть «расширены» в дочернем классе или в реализации интерфейса, поскольку расширенный тип по-прежнему выполняет контракт интерфейса/родительского класса. Это означает, что параметры дочернего класса могут объявлять тип с помощью Union-типа, включающего больше типов, или имени класса, являющегося родительским для текущего класса.

Когда тип параметра объявлен как  mixed , это практически исключает дальнейшую контравариантность, поскольку  mixed  уже включает в себя все типы, с которыми работает PHP.  По возможности всегда выбирайте более конкретные типы, потому что как только вы помечаете тип параметра как  mixed  в публичном API, все дочерние классы должны быть способны обрабатывать смешанные типы. 

Ковариантность: возвращаемые типы  mixed  

Если метод родительского класса объявил возвращаемый тип, отличный от  mixed , дочерним классам будет запрещено объявлять  mixed , поскольку это расширяет область возвращаемого типа и тем самым нарушает LSP. 

class A {
    public function foo(): mixed {}
}
class B extends A{
    public function foo(): void {}
} 

Приведенный выше код приведет к фатальной ошибке:

Fatal error: Declaration of B::foo(): void must be compatible with A::foo(): mixed 

Это связано с тем, что   mixed  не включает в себя тип  void . Если возвращаемый тип не объявлен явно, предполагается, что это  mixed|void . 

Все следующие объявления разрешены:

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 : Разрешено: сужает предполагаемый возвращаемый тип  mixed|void  метода  A::foo .
  •  B::bar : Разрешено: сужает предполагаемый возвращаемый тип  mixed|void  метода  A::bar .
  •  B::baz : Разрешено: сужает объявленный тип  mixed .

Инвариантность: типы свойств  mixed  

Если тип свойства объявлен как  mixed , этот тип нельзя опускать или изменять вообще.

Использование с  void  

PHP поддерживает псевдотип возвращаемого значения  void , указывающий на то, что функция ничего не возвращает. Это эквивалентно отсутствию инструкции  return  или выражению  return;  без явного значения.

Тип  void  и  mixed   не могут быть объединены в union. Кроме того,   mixed  не включает  void .

Nullable-типы  mixed  

Запрещено объявлять тип  mixed  как nullable, поскольку   mixed  уже включает в себя  null .

Все следующие объявления недопустимы:

function foo(mixed|null $foo) {}
function foo(?mixed $foo) {}
function foo($foo): mixed|null {}
function foo($foo): ?mixed {} 

Все вышеперечисленные объявления вызовут фатальную ошибку:

Fatal error: Type mixed can only be used as a standalone type in ... on line ... 

Практическое использование

Многие встроенные функции PHP принимают различные типы, которые теперь можно объявлять с помощью типа  mixed . Однако для пользовательских функций зачастую лучше использовать конкретный тип или Union-тип. 

Такие функции, как  var_dump  или  get_debug_type() , могут объявлять свои параметры как  mixed , поскольку по определению они принимают любой тип. 

Если вы объявляете параметр, возвращаемый тип или свойство класса с типом  mixed , имейте в виду, что  mixed  включает такие типы, как  resource  и  callable , которые непросто сохранить, сериализовать, очистить (санитизировать) или отобразить. 

Большинству пользовательских функций, которым нужно «принимать что угодно» (например, функциям логирования), лучше подойдут Union-типы, такие как  string|int|float|bool|null|object|array .

Обратная совместимость

 mixed  является мягко зарезервированным словом начиная с PHP 7. До PHP 8 технически было возможно объявить класс с именем  mixed , и это не вызывало никаких ошибок, предупреждений или замечаний. Стандарт PHPDoc широко использовал  mixed  в качестве объявления типа, поэтому крайне маловероятно, что даже в самых нестандартных кодовых базах найдется класс с именем  mixed .

Попытка объявить класс с именем  mixed  в PHP 8 приведет к следующей ошибке:

Fatal error: Cannot use 'mixed' as class name as it is reserved in ... on line ... 

Полифил

Эту функциональность невозможно реализовать через полифил, поскольку это встроенный внутренний тип. Если вы используете тип  mixed  где-либо в своем коде, убедитесь, что он всегда будет выполняться в среде PHP 8+.