• PHP
【php8上級/準上級試験】模擬問題解説 問題5.

「第1回 PHP 8 上級 模擬試験」を解説していきます

本記事ではひたすら下記記事の模擬試験の解説をしていきたいと思います!

第1回 PHP 8 上級 模擬試験
https://study.prime-strategy.co.jp/study/ph8ex1/

解説記事一覧

模擬問題 5

メソッドに関する説明の中で、誤っているものを1つ選びなさい。
なお「\」はバックスラッシュに読み替えること。
また、すべてのコードの先頭には下記のコードが書かれているものとする。

declare(strict_types=1);
error_reporting(-1);

__toString() メソッドにより、クラスが文字列に変換される際の動作を決めることができる。
そのため、以下のコード

class Hoge {
    public function __toString() {
        return $this->s;
    }

    private $s = 'string';
}

$obj = new Hoge();
echo 'object: ' . $obj , PHP_EOL;

は正しく実行でき、結果は object: string となる。

また、__toString() メソッドで例外を投げる事は、PHP 7.3 までは出来なかったが、PHP 7.4 からは出来るようになった。
そのため、以下のコード

class Hoge {
    public function __toString() {
        throw new \Exception('*** test string ***');
    }

    private $s = 'string';
}

try {
    $obj = new Hoge();
    echo 'object: ' . $obj, PHP_EOL;
} catch(\Throwable $e) {
    echo $e->getMessage(), PHP_EOL;
}

を実行すると *** test string *** となる。

__toString()について

__toString() メソッドは、「オブジェクトを文字列として扱うときに、どんな文字列にするか」を決めるメソッドです。

例えば、echo したり、文字列と結合したりするときに、このメソッドが自動で呼び出されます。

そのうえで、「PHP 7.4 以降は __toString() でも例外を投げられる」ようになりましたので、

問題文では下記の流れで例外がキャッチされます

  1. $obj文字列として扱おうとしている
  2. __toString()自動的に呼ばれる
  3. __toString() の中で throw new \Exception('*** test string ***'); を実行

よって選択肢は⭕です

__invoke() メソッドは、 スクリプトがオブジェクトを関数としてコールしようとした際にコールされる。
そのため、以下のコード

class Hoge {
    public function __invoke() {
        var_dump($this);
        return 'string';
    }
}

$obj = new Hoge();
$r = $obj();
var_dump($r);

は正しく実行でき、結果は次のとおりとなる。

object(Hoge)#1 (0) {
}
string(6) "string"

__invoke() メソッド

__invoke() メソッドは、 スクリプトがオブジェクトを関数としてコールしようとした際にコールされます。

なので問題だと$objはオブジェクトですが、$obj();関数として呼び出されているので__invokeが呼び出されます

⬇️

var_dump($this)の処理について

そもそも$thisとは

$thisは現在のオブジェクトインスタンスを指す特別な変数

var_dumpでオブジェクトを出力するときのフォーマット

object(クラス名)#オブジェクトID (プロパティの数) { プロパティの内容 }

class Test {}
$obj = new Test();
var_dump($obj);
// 出力: object(Test)#1 (0) { }

var_dumpで文字列を出力するときのフォーマット

object(クラス名)#オブ$str = "hello";
var_dump($str);
// 出力: string(5) "hello"ジェクトID (プロパティの数) { プロパティの内容 }

となるので問題文の通りの出力結果となり選択肢は⭕です