ツイート
シェア
LINEで送る
B! はてぶでブックマーク
Pocketでブックマーク
RSSフィード

PHP8, Stringableインタフェース, 文字列への変換(キャスト)を強制するクラスにする

php
イラストダウンロードサイト【イラストAC】
の画像をもとに加工しています。

PHP8で新たに追加されたStringableインタフェースは、オブジェクトから文字列へ変換するクラスに強制的になります。

強制して無理やりデータ型をstringにするので型チェックしているのと同じになるという機能。

このインタフェースを実装するクラスは __toString() メソッドを用意するだけのシンプルな作り。

Stringableを実装したクラスのサンプル

Stringableインタフェースをimplementsしたクラスはかんたんなので、いきなりクラスの内容から見てみましょう。

class Test implements Stringable
{
    private $val1;
    private $val2;
    private $val3;

    public function __construct($val1, $val2, $val3)
    {
        $this->val1 = $val1;
        $this->val2 = $val2;
        $this->val3 = $val3;
    }

    public function __toString(): string
    {
        return sprintf('%s, %s, %s', $this->val1, $this->val2, $this->val3);
    }
}

$val = new Test(1, 2, 3);

var_dump($val);

echo $val;
echo PHP_EOL;
print $val;
echo PHP_EOL;

var_dump('change to string: ' . $val);
var_dump(sprintf('sprintf: %s', $val));
実行結果
object(Test)#1 (3) {
  ["val1":"Test":private]=>
  int(1)
  ["val2":"Test":private]=>
  int(2)
  ["val3":"Test":private]=>
  int(3)
}
1, 2, 3
1, 2, 3
string(25) "change to string: 1, 2, 3"
string(16) "sprintf: 1, 2, 3"

Stringableは __toString() の実装を強制する

Stringableインタフェースの中身はシンプルです。__toString() メソッドの実装をクラスに強制するだけ。

このメソッドは名前の通り、文字列を返すようにしてください。

戻り値の型をstring以外にして処理を実行すると Fatal Error(致命的なエラー)になります。

戻り値をintに変えてみると...
    public function __toString(): int
    {
        return sprintf('%s, %s, %s', $this->val1, $this->val2, $this->val3);
    }
実行結果
PHP Fatal error:  Test::__toString(): Return type must be string when declared in /home/vagrant/php-test.php on line 14

そもそもこのインタフェースでは __toString() の戻り値の型まで指定されているので、string以外は指定できません。

動かして確かめるまでもなく、phpcsなどの静的コードチェックで構文エラーになります。

phpcsの構文エラー
Test::__toString(): Return type must be string when declared

ただし注意が必要なのは、メソッドの戻り値の型の未指定では構文エラーになりません。

このとき処理を動かすと、型がstring以外はstring型にキャストします。

(キャストできないものは警告・エラーになる。)

型指定を省略して int を返すと...
    public function __toString()
    {
        return $this->val1 + $this->val2 + $this->val3;
    }
実行結果
object(Test)#1 (3) {
  ["val1":"Test":private]=>
  int(1)
  ["val2":"Test":private]=>
  int(2)
  ["val3":"Test":private]=>
  int(3)
}
6
6
string(19) "change to string: 6"
string(10) "sprintf: 6"

動かないと分からないコードはよろしくないし、PHP8からは型の厳密化が進んでいるので型を指定しましょう。

__toString() はマジックメソッド。直接コールできない。

__toString()は、メソッド名の頭に '__' がついているので直接コールはできません。これをマジックメソッドといいます。

(コンストラクタがその代表例。)

__toString() が起動するタイミングは、クラスインスタンスを文字列として扱ったときや、echo, printで出力するときです。

それ以外は発動しません。

さっきからサンプルコードの処理結果で不思議に思ったでしょう。

var_dump() で出力したときはクラスオブジェクトなのに、 echo, printではインタンスをそのまんま出力しているのに、__toString()の結果が出ているから。

これが Stringableインタフェースの真骨頂です。というかこれ以外の機能はない。

ちょっとひねって、こういうときも__toString() が発動します。

インスタンスをstringにキャスト
var_dump((string)$val);
実行結果
string(7) "1, 2, 3"

PHP公式ドキュメント

マジックメソッド

クラスオブジェクトはクラスオブジェクト。データ型が変わるわけじゃない。

クラスインスタンスはあくまでクラスインスタンスなので、文字列として扱ったあともその状態は保持します。

var_dump($val);
echo 'change to string: ' . $val . PHP_EOL;
var_dump($val);
object(Test)#1 (3) {
  ["val1":"Test":private]=>
  int(1)
  ["val2":"Test":private]=>
  int(2)
  ["val3":"Test":private]=>
  int(3)
}
change to string: 1, 2, 3
object(Test)#1 (3) {
  ["val1":"Test":private]=>
  int(1)
  ["val2":"Test":private]=>
  int(2)
  ["val3":"Test":private]=>
  int(3)
}
前の投稿
PHP8, ::classがクラスオブジェクトでも使える。get_class() と同じ。
PHP8, 部分文字列を扱う新しい関数の追加。新機能というより関数の意図の整理。
次の投稿
コメントを残す

*