「第1回 PHP 8 上級 模擬試験」を解説していきます
本記事ではひたすら下記記事の模擬試験の解説をしていきたいと思います!
第1回 PHP 8 上級 模擬試験
https://study.prime-strategy.co.jp/study/ph8ex1/
Contents
解説記事一覧
- 【php8上級/準上級試験】模擬問題解説 問題1.~ 3. abstract staticメソッド
- 【php8上級/準上級試験】模擬問題解説 問題4. __construct() __destruct __call() __callStatic()
- 【php8上級/準上級試験】模擬問題解説 問題5. __toString() 「例外を投げる(throw new \Exception)とは?」 __invoke() __get() __debugInfo()
- 【php8上級/準上級試験】模擬問題解説 問題6. &参照(リファレンス)unset()
- 【php8上級/準上級試験】模擬問題解説 問題7. 名前空間とグローバル空間 use エイリアス(as)
- 【php8上級/準上級試験】模擬問題解説 問題8. error_reporting set_error_handler() 例外捕捉
- 【php8上級/準上級試験】模擬問題解説 問題9. interface implements ArrayAccess
- 【php8上級/準上級試験】模擬問題解説 問題10. SPL RecursiveDirectoryIterator RecursiveIteratorIterator SplFileInfo SplFileObject
- 【php8上級/準上級試験】模擬問題解説 問題11. $_SERVER $GLOBALS $argv $_COOKIE
- 【php8上級/準上級試験】模擬問題解説 問題12. list() iterable
- 【php8上級/準上級試験】模擬問題解説 問題13. 可変変数
- 【php8上級/準上級試験】模擬問題解説 問題14. クラスの型宣言 Null合体代入演算子(??=)
- 【php8上級/準上級試験】模擬問題解説 問題15. private final
- 【php8上級/準上級試験】模擬問題解説 問題16. break文
- 【php8上級/準上級試験】模擬問題解説 問題17. XSS (クロスサイトスクリプティング) htmlspecialchars()
- 【php8上級/準上級試験】模擬問題解説 問題18. $_FILES
- 【php8上級/準上級試験】模擬問題解説 問題19. CSRF (Cross-Site Request Forgery) random_bytes()
- 【php8上級/準上級試験】模擬問題解説 問題20. $_SESSION
- 【php8上級/準上級試験】模擬問題解説 問題21. ガベージコレクション xdebug_debug_zval()
- 【php8上級/準上級試験】模擬問題解説 問題22. Directory DirectoryIterator SeekableIterator
- 【php8上級/準上級試験】模擬問題解説 問題23.
模擬問題 4
メソッドに関する説明の中で、誤っているものを1つ選びなさい。
なお、すべてのコードの先頭には下記のコードが書かれているものとする。
declare(strict_types=1);
error_reporting(-1);
declare(strict_types=1);とは指定された型に厳密に従わないとエラーとなります
error_reporting(-1);は全てのエラーを報告します
PHP において、コンストラクタは、__construct() メソッドで実装される。
そのため、以下のコード
class Hoge {
public function __construct() {
echo __METHOD__, PHP_EOL;
}
}
$obj = new Hoge();
は正しく実行でき、結果は Hoge::__construct となる。
なお、コンストラクタを有している場合、親クラスのコンストラクタが暗黙の内にコールされることはない。
そのため、以下のコード
class Hoge {
public function __construct() {
echo __METHOD__, PHP_EOL;
}
}
class Foo extends Hoge{
public function __construct() {
echo __METHOD__, PHP_EOL;
}
}
$obj = new Foo();
を実行すると、結果は Foo::__construct となる。
親クラスのコンストラクタを実装する場合には、parent::をコールする事が必要となる。
そのため、以下のコード
class Hoge {
public function __construct() {
echo __METHOD__, PHP_EOL;
}
}
class Foo extends Hoge{
public function __construct() {
parent::__construct();
echo __METHOD__, PHP_EOL;
}
}
$obj = new Foo();
を実行すると、結果は次のとおりとなる。
Hoge::__construct
Foo::__construct
今回の問題でのポイントは子クラスでのコンストラクタの継承についてになります。
そもそも「コンストラクタ」とは
コンストラクタは「最初の設定をする特別な関数」
- 新しいものを作るときの「最初の設定」
- 必ず必要な情報を設定できる
- クラスから実体(インスタンス)を作る時に自動的に動く
子クラスで新しいコンストラクタを定義すると、親のコンストラクタは自動で呼ばれない
PHPでは、子クラスに新しいコンストラクタを定義すると、親クラスのコンストラクタは自動的に呼ばれず、必要に応じて parent::__construct() を明示的に呼び出す必要があります。
一方、子クラスでコンストラクタを定義しない場合は、親クラスのコンストラクタがそのまま継承され、自動的に呼び出されます。
今回の問題文は親のコンストラクタの呼び出しもしてあるので、親と子両方のコンストラクタが実行されます。よって選択肢は⭕です
PHP において、デストラクタは、__destruct()
メソッドで実装される。
そのため、以下のコード
class Hoge {
public function __destruct() {
echo __METHOD__, PHP_EOL;
}
}
$obj = new Hoge();
は正しく実行でき、結果は Hoge::__destruct となる。
なお、デストラクタを有している場合、親クラスのデストラクタは、暗黙の内にコールされる。コールされる順番は「子クラスのデストラクタ → 親クラスのデストラクタ」の順番である。
そのため、以下のコード
class Hoge {
public function __destruct() {
echo __METHOD__, PHP_EOL;
}
}
class Foo extends Hoge{
public function __destruct() {
echo __METHOD__, PHP_EOL;
}
}
$obj = new Foo();
を実行すると、結果は次のとおりとなる。
Foo::__destruct
Hoge::__destruct
選択肢2でのポイントはデストラクタですね
デストラクタとは?
デストラクタは、オブジェクトが破棄(削除)される時に自動的に呼び出されるメソッドです。 PHPでは __destruct()
という名前で定義します。
クラス継承において親クラスのデストラクタは自動的に呼び出されます。
<?php
class ParentClass {
public function __destruct() {
echo "親のデストラクタ実行\n";
}
}
class ChildClass extends ParentClass {
}
$obj = new ChildClass();
// 実行結果
親のデストラクタ実行
ただし
子クラスでデストラクタの定義がある場合は親のデストラクタは呼び出されません
(※ 親クラスのデストラクタの処理も必要であれば、子クラスの __destruct() の中で parent::__destruct() を明示的に呼ぶ必要があります)
<?php
class ParentClass {
public function __destruct() {
echo "親のデストラクタ実行\n";
}
}
class ChildClass extends ParentClass {
public function __destruct() {
echo "子のデストラクタ実行\n";
}
}
$obj = new ChildClass();
// 実行結果
子のデストラクタ実行
上記より親クラスのデストラクタが呼び出されず、子クラスのデストラクタのみ実行されます!
選択肢は❌です
__call() マジックメソッドを使うと「アクセス不能なメソッドがオブジェクトのコンテキストで呼び出された時」に、処理を入れる事ができる。
そのため、以下のコード
class Hoge {
public function __call(string $name, array $arguments) {
echo "call: {$name}", PHP_EOL;
var_dump($arguments);
echo PHP_EOL;
}
}
$obj = new Hoge();
$obj->test();
$obj->test2(1, '2', [3]);
は正しく実行でき、結果は次のとおりとなる。
call: test
array(0) {
}
call: test2
array(3) {
[0]=>
int(1)
[1]=>
string(1) "2"
[2]=>
array(1) {
[0]=>
int(3)
}
}
__callの動作
__call()
は未定義のインスタンスメソッドが呼ばれた時に実行されます。
第1引数の$method
には呼び出されたメソッド名が入る 第2引数の$args
には引数が配列として渡されます。
よって選択肢は⭕です。
__callStatic() マジックメソッドを使うと「アクセス不能なメソッドが静的コンテキストで呼び出された時」に、処理を入れる事ができる。
そのため、以下のコード
class Hoge {
public static function __callStatic(string $name, array $arguments) {
echo "call: {$name}", PHP_EOL;
var_dump($arguments);
}
}
Hoge::test(1, '2', [3]);
は正しく実行でき、結果は次のとおりとなる。
call: test
array(3) {
[0]=>
int(1)
[1]=>
string(1) "2"
[2]=>
array(1) {
[0]=>
int(3)
}
}
なお、__callStatic() マジックメソッドが動くのは「静的コンテキストで呼び出された時」だけのため、「オブジェクトのコンテキストで呼び出された時」には動かない。
そのため、以下のコード
class Hoge {
public static function __callStatic(string $name, array $arguments) {
echo "call: {$name}", PHP_EOL;
var_dump($arguments);
}
}
$obj = new Hoge();
$obj->test();
を実行すると、結果は次のとおりとなる。
Fatal error: Uncaught Error: Call to undefined method Hoge::test() in …
__callStaticの呼び出し
流れとしては下記です
- 静的メソッドを呼び出します
- PHPはそのメソッドが実際にクラスに存在するかチェックします
- メソッドが存在しない場合、自動的に
__callStatic
が呼び出されます
注意)
__callStaticインスタンス呼び出しではエラー
静的メソッドでない場合は「__callStatic」呼び出しはできません、よって選択肢は⭕です!
インスタンス(静的メソッドでない場合)は__call()を使用します!