基礎

PHPの__toStringメソッド|オブジェクトを文字列に変換する方法

PHPの__toString()は、オブジェクトを文字列として扱おうとしたときに自動的に呼び出されるマジックメソッドです。echo や文字列結合などでオブジェクトが文字列コンテキストに置かれると、このメソッドの戻り値が使われます。

デバッグ時のオブジェクト表示や、テンプレートでのオブジェクト出力、ログ記録など、オブジェクトを人間が読める形式に変換する際に非常に便利な機能です。

基本的な使い方

PHP
<?php
class User {
    public function __construct(
        private string $name,
        private int $age
    ) {}

    public function __toString(): string {
        return "{$this->name}({$this->age}歳)";
    }
}

$user = new User("田中", 30);

// echoで自動的に__toString()が呼ばれる
echo $user . "\n";

// 文字列結合でも呼ばれる
echo "ユーザー: " . $user . "\n";

// (string)キャストでも呼ばれる
$str = (string)$user;
echo "変換結果: {$str}\n";
実行結果
田中(30歳)
ユーザー: 田中(30歳)
変換結果: 田中(30歳)

__toString() を定義していないクラスのオブジェクトを echo しようとすると、Fatal Errorが発生します。

値オブジェクトでの活用

PHP
<?php
class Money {
    public function __construct(
        private int $amount,
        private string $currency = "JPY"
    ) {}

    public function add(Money $other): Money {
        return new Money($this->amount + $other->amount, $this->currency);
    }

    public function __toString(): string {
        if ($this->currency === "JPY") {
            return number_format($this->amount) . "円";
        }
        return "$" . number_format($this->amount / 100, 2);
    }
}

$price1 = new Money(1500);
$price2 = new Money(2300);
$total = $price1->add($price2);

echo "商品A: {$price1}\n";
echo "商品B: {$price2}\n";
echo "合計: {$total}\n";

$usd = new Money(1999, "USD");
echo "ドル: {$usd}\n";
実行結果
商品A: 1,500円
商品B: 2,300円
合計: 3,800円
ドル: $19.99

デバッグや一覧表示での活用

PHP
<?php
class Product {
    public function __construct(
        private string $name,
        private int $price,
        private int $stock
    ) {}

    public function __toString(): string {
        $status = $this->stock > 0 ? "在庫あり" : "在庫なし";
        return "[{$this->name}] {$this->price}円({$status})";
    }
}

$products = [
    new Product("PHP入門書", 2980, 50),
    new Product("JavaScript大全", 3500, 0),
    new Product("Pythonガイド", 2200, 12),
];

echo "=== 商品一覧 ===\n";
foreach ($products as $i => $product) {
    echo ($i + 1) . ". {$product}\n";
}

// implodeでも使える
echo "\n全商品: " . implode(" / ", $products) . "\n";
実行結果
=== 商品一覧 ===
1. [PHP入門書] 2980円(在庫あり)
2. [JavaScript大全] 3500円(在庫なし)
3. [Pythonガイド] 2200円(在庫あり)

全商品: [PHP入門書] 2980円(在庫あり) / [JavaScript大全] 3500円(在庫なし) / [Pythonガイド] 2200円(在庫あり)

実用的な例

PHP
<?php
class Color {
    public function __construct(
        private int $r,
        private int $g,
        private int $b
    ) {}

    public function __toString(): string {
        return sprintf("#%02x%02x%02x", $this->r, $this->g, $this->b);
    }

    public static function fromHex(string $hex): self {
        $hex = ltrim($hex, "#");
        return new self(
            hexdec(substr($hex, 0, 2)),
            hexdec(substr($hex, 2, 2)),
            hexdec(substr($hex, 4, 2))
        );
    }
}

$red = new Color(255, 0, 0);
$green = Color::fromHex("#00ff00");
$blue = new Color(0, 0, 255);

echo "赤: {$red}\n";
echo "緑: {$green}\n";
echo "青: {$blue}\n";
実行結果
赤: #ff0000
緑: #00ff00
青: #0000ff
ポイント

__toString() は必ず string 型を返す必要があります。整数や配列を返すとエラーになります。PHP 8.0以降では、Stringable インターフェースが自動的に実装されるため、Stringable 型の引数に __toString() を持つオブジェクトを渡せます。

注意

PHP 7.4以前では __toString() 内で例外をスローするとFatal Errorになります。PHP 8.0以降は例外をスローできるようになりましたが、__toString() 内の処理はシンプルに保つのが無難です。

まとめ

  • __toString() はオブジェクトを文字列として扱うときに自動で呼ばれる
  • echo、文字列結合、(string) キャストで自動的に呼び出される
  • 値オブジェクトやデバッグ表示に最適
  • 必ず string 型を返す必要がある
  • PHP 8.0で Stringable インターフェースが自動実装される