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 メソッドがもしあったら的な実装ができます。