【PHP】bool でキャストすると false になりうるインスタンスをつくる

  • 2021年11月16日
  • 2021年11月16日
  • PHP
function echoCastBoolResult($obj): void
{
	$bool = (bool)$obj;
	if(is_object($obj) && $bool === false){
	  echo "成功";
	}else{
	  echo "失敗";
	}
}

 ↑のコードで”成功”と echo されるオブジェクトの生成方法を紹介します。このオブジェクトはあるクラスをインスタンス化したオブジェクトです。この記事で紹介する方法はあくまでこういうこともできるといった紹介であり、実際にコードを書く時にはオブジェクトのプロパティなり、メソッドなりに bool 値を持たせた方がいいです。例としては次です。

$obj->isSuccess();// 成功についての bool を取得するメソッドの使用例

 bool でキャストすると false になりうるインスタンスを生成するために使うのは SimpleXMLElement クラスです。このクラスは PHP の中ではキャストした場合 false になりうる組み込みクラスです。普通の object が必ず true になるのに対し、これは false になりえます。
PHP: SimpleXMLElement – Manual
PHP: 論理型 (boolean) – Manual
 具体的には次の様に動きます。

<?php

// 空 XML を bool にキャストすると false
$falsy = new SimpleXMLElement('<bool></bool>');
var_dump((bool)$falsy);// false

// 中身のある XML を bool にキャストすると true
$truthy = new SimpleXMLElement('<bool><true/></bool>');
var_dump((bool)$truthy);// true


// echoCastBoolResult(new SimpleXMLElement('<bool></bool>')); // 成功

Online PHP editor | output for 2TOTI# ↑のデモ
 これだけも目的は達成できているのですが、SimpleXMLElement を継承することによってて true と false を行き来するコードを作ることもできます。これは次でできます。

<?php

class CanCastBool extends SimpleXMLElement
{
    /**
     * XML を意識しないコンストラクタ
     * @return CanCastBool
     */
    public static function makeInstance(): CanCastBool
    {
        $instance =  new self('<bool></bool>');
        $instance->true = true;

        return $instance;
    }

    public function toTrue(): void
    {
        if(empty($this->true)){
            $this->addChild('true');
        }
    }

    public function toFalse(): void
    {
        unset($this->true);
    }
}

$a = CanCastBool::makeInstance();
echo "---init----\n";
var_dump((bool)$a);// true
echo "----------\n";
$a->toFalse();
var_dump((bool)$a);// false
echo "----------\n";
$a->toTrue();
var_dump((bool)$a);// true
echo "----------\n";
$a->toFalse();
var_dump((bool)$a);// false
echo "----------\n";
$a->toTrue();
var_dump((bool)$a);// true

 toTrue で自身を空でなくし、toFalse で自身を空にすることによって true と false を切り替えられます。自身を空にする都合上、直にプロパティを持てないのですが、これは PHP8 で追加された WeakMap を用いることで解決できます。WeakMap はオブジェクトをキーにする辞書であり、プロパティを取りに行く際はこの自身をキーにしてこの辞書に自分のプロパティは何か、と尋ねに行きます。
PHP: WeakMap – Manual
 これの実装とデモが次です。
↓のデモ Online PHP editor | output for kBnZJ

<?php

class CanCastBool extends SimpleXMLElement
{
    /** @var WeakMap 各 CanCastBool インスタンスのプロパティを保持する WeakMap */
    public static WeakMap $properties;

    /**
     * XML を意識しないコンストラクタ
     * @param  string  $fuga
     * @return CanCastBool
     */
    public static function makeInstance(string $fuga): CanCastBool
    {
        $instance =  new self('<bool></bool>');
        $instance->true = true;

        self::$properties ??= new WeakMap();
        // WeakMap に自分をキーにしてプロパティを記録させる
        // WeakMap に退避させておくので XML とは別の扱いになる
        self::$properties[$instance] = [
            'fuga' => $fuga,
        ];

        return $instance;
    }

    /** プロパティ的に読み取るメソッド。WeakMap から取ってくる */
    public function getP(string $name)
    {
        return self::$properties[$this][$name];
    }

    /** プロパティ的にセットするメソッド。WeakMap にセットする */
    public function setP($name, $value)
    {
        self::$properties[$this][$name] = $value;
    }


    public function toTrue(): void
    {
        $this->true = true;
    }
    public function toFalse(): void
    {
        unset($this->true);
    }
}

/*
 * 複数の別インスタンスを用意しても混線せず
 * キャスト結果の true、false に関わらずプロパティを書き換えられます 
 */
$a = CanCastBool::makeInstance('fugafuga');
$b = CanCastBool::makeInstance('piyopiyo');

echo "---init----\n";
var_dump((bool)$a);// true
var_dump($a->getP('fuga'));// 'fugafuga'
$a->setP('fuga', 'foo');
$a->setP('hoge', 'bar');

echo "----------\n";
$a->toFalse();
var_dump((bool)$a);// false
var_dump($a->getP('fuga'));// 'foo'
var_dump($a->getP('hoge'));// 'bar'
$a->setP('hoge', 'hogehoge');

echo "----------\n";
$a->toTrue();
var_dump((bool)$a);// true
var_dump($a->getP('fuga'));// 'foo'
var_dump($a->getP('hoge'));// 'hogehoge'
var_dump($b->getP('fuga'));// 'piyopiyo'

 機能のための継承というダメな継承の使い方ですし、実用性はそれほどありませんがこんな感じで __toBoolean メソッドがもしあったら的な実装ができます。

>株式会社シーポイントラボ

株式会社シーポイントラボ

TEL:053-543-9889
営業時間:9:00~18:00(月〜金)
住所:〒432-8003
   静岡県浜松市中央区和地山3-1-7
   浜松イノベーションキューブ 315
※ご来社の際はインターホンで「316」をお呼びください

CTR IMG