__tostring()
Узнайте, как магический метод PHP __toString() позволяет объекту задать своё строковое представление, с примерами и правилами PHP.
Магический метод __toString()
__toString() — один из магических методов PHP, то есть специальных методов, которые PHP вызывает автоматически в определённых ситуациях. В частности, PHP вызывает __toString() всякий раз, когда объект используется там, где ожидается строка: в echo, print, при конкатенации через ., внутри строк в двойных кавычках, при передаче в функцию с тайп-хинтом string и т. д.
Без __toString() попытка использовать объект как строку вызывает ошибку:
Object of class Foo could not be converted to stringОпределив __toString(), вы решаете, как будет выглядеть это строковое представление. На этой странице рассматриваются сигнатура метода, правила PHP, рабочие примеры и типичные подводные камни.
Зачем это нужно
__toString() используют, когда объект имеет осмысленную текстовую форму и вы хотите, чтобы он «просто работал» в строковых контекстах. Типичные случаи:
- Объект
Money, который должен отображаться как"$19.99". - Объект
User, который должен выводить полное имя в шаблоне. - Объект-значение (дата, URL, координата), который нужно логировать или выводить через
echoбез вызова геттера каждый раз.
Это делает вызывающий код чище — echo $user; вместо echo $user->getFullName();.
Синтаксис
public function __toString(): stringМетод не принимает аргументов и должен возвращать строку. Начиная с PHP 8.0, возвращаемый тип : string неявно применяется даже если вы его опустите — возврат чего-либо другого вызывает TypeError.
Базовый пример
Здесь мы задаём объекту Money читаемую строковую форму:
<?php
class Money
{
public function __construct(
private int $cents,
private string $currency = 'USD'
) {}
public function __toString(): string
{
$amount = number_format($this->cents / 100, 2);
return "{$amount} {$this->currency}";
}
}
$price = new Money(1999);
echo $price; // 19.99 USD
echo "Total: {$price}"; // Total: 19.99 USDВы можете запустить этот пример с помощью кнопки выше.
Когда выполняется echo $price, PHP видит объект там, где нужна строка, и за кулисами вызывает $price->__toString(), используя возвращённое значение. То же самое происходит внутри строки в двойных кавычках "Total: {$price}".
__toString() должен возвращать строку
Возвращаемый тип : string означает, что PHP должен получить строку. Скалярные значения вроде 42 приводятся к "42" автоматически, но значения, которые нельзя привести — например, массив — вызывают TypeError:
<?php
class Broken
{
public function __toString(): string
{
return [1, 2]; // wrong: an array cannot become a string
}
}
echo new Broken();
// TypeError: Broken::__toString(): Return value must be of type string, array returnedВсегда формируйте и возвращайте настоящую строку, чтобы преобразование было явным и не преподносило сюрпризов.
Интерфейс Stringable
Начиная с PHP 8.0, любой класс, в котором объявлен __toString(), автоматически реализует встроенный интерфейс Stringable. Вы можете использовать тайп-хинт Stringable (или string|Stringable), чтобы принимать «всё, что может стать строкой»:
<?php
function greet(string|Stringable $who): void
{
echo "Hello, {$who}!\n";
}
class Name implements Stringable
{
public function __construct(private string $value) {}
public function __toString(): string
{
return $this->value;
}
}
greet('world'); // Hello, world!
greet(new Name('Ada')); // Hello, Ada!Явное указание implements Stringable необязательно (PHP добавляет его сам), но делает ваши намерения понятными для читателей и инструментов статического анализа.
Подводные камни
- Вы не можете использовать
throwвнутри__toString()до PHP 7.4. Начиная с PHP 7.4 исключения разрешены; в более старых версиях выброс исключения внутри__toString()приводил к фатальной ошибке. Держите метод простым и без побочных эффектов. - Метод должен быть
public. Приватный или защищённый__toString()не будет вызван в строковом контексте. - Явное приведение
(string)тоже вызывает его.(string) $object— явный способ вызвать__toString().
Заключение
__toString() позволяет объекту определить собственное строковое представление, чтобы его можно было выводить через echo, конкатенировать и интерполировать как обычную строку. Делайте метод чистым, всегда возвращайте строку и рассмотрите возможность использования тайп-хинта Stringable, когда функция должна принимать как строки, так и строкоподобные объекты. Для более глубокого изучения смотрите PHP Classes and Objects, магический метод конструктор __construct() и PHP Strings.