へろへろもへじ

(ブログタイトル募集中)

【PHP】『trait』 + 『リフレクション』で__toString()を拡張してみた

PHPerの皆様、『__toString()』って独自に実装していますか?

自分は、Javaでプログラム書いてた前職ではEntityとかDTOとかいわゆる、プロパティの集合クラスにはほぼ必ず実装してました。

PHPではそこのところどうなのでしょ?(PHP界隈に詳しい方、コメントください!!)

さて、Java脳の私は前回ブログで書いたEnumと同じくらいtoStringにはお世話になりまして、
PHPでも同じことを実現したいなーと思い立ち、
Javaerの方にはお馴染みの、Apache CommonsのToStringBuilder#reflectionToString()を参考に、『trait』と『リフレクション』を使って実装してみました。

■ToString.php

<?php 

/**
 * オブジェクトのプロパティを表示するための__toStringのtraitです
 */
trait ToString
{
    public function __toString()
    {
        return self::reflectionToString($this);
    }

    private static function reflectionToString($obj)
    {
        $propertyStr = '';

        $reflClass = new ReflectionClass($obj);
        $properties = $reflClass->getProperties();

        foreach ($properties as $property) {
            $property->setAccessible(true);

            $name = $property->getName();
            $value = $property->getValue($obj);
            $type = gettype($value);

            $propertyStr .= ',' . $name . '=' . $value . '<' . $type . '>';
        }

        $result = get_class($obj) .'[';
        $result .= substr($propertyStr, 1) . ']';

        return $result;
    }
}

上記のtraitを組み込んで、__toStringを拡張します。
例としてプロパティのみ持ったクラスを作ってみます。

■Hoge.php

<?php 

class Hoge
{
    private $name;

    private $foo;

    private $bar;

    // traitを組み込む
    use ToString;
    
    public function getName()
    {
        return $this->name;
    }

    public function setName($name)
    {
        $this->name = $name;

        return $this;
    }

    public function getFoo()
    {
        return $this->foo;
    }

    public function setFoo($foo)
    {
        $this->foo = $foo;

        return $this;
    }

    public function getBar()
    {
        return $this->bar;
    }

    public function setBar($bar)
    {
        $this->bar = $bar;

        return $this;
    }
}

では、__toStringの出力を検証するコードを書いてみます。

■tostring_test.php

<?php 

require 'ToString.php';
require 'Hoge.php';

$hoge = new Hoge();
$hoge->setName('Taro');
$hoge->setFoo('Hi-Ha-');
$hoge->setBar('Guhehe');

echo $hoge . PHP_EOL;

上記スクリプトの実行結果が以下になります。
※実行はSublimeText2上から

Hoge[name=Taro<string>,foo=Hi-Ha-<string>,bar=Guhehe<string>]
[Finished in 0.0s]


こんな感じで、意外にさくっと実装できました。言語は変われどやはりtoStringは超便利です!
それではーノシ

参考サイト