こんにちは。PHP技術者認定機構 CTOの古庄道明です。
今日もPHP8上級試験の模擬問題と解説を紹介します。
以下を解いて出題のイメージと知識を補っていただけると幸いです。
問題
名前空間に関する説明の中で、誤っているものを1つ選びなさい。
すべてのコードには、declare(strict_types=1); がファイル先頭に、error_reporti
ng(-1); が namespace 宣言後の適切な箇所に書かれているものとする。
選択肢
選択肢1
名前空間は、namespace キーワードを使って宣言する。
名前空間の宣言は、通常他のコードより前にファイルの先頭で宣言する必要がある。
名前空間の宣言前に書かれたクラスなどは、宣言された名前空間には含まれない。
そのため、以下のコード
class Hoge {
}
namespace Name;
class Foo {
}
$obj = new Hoge();
var_dump($obj);
を実行すると、結果は次のとおりとなる。
Fatal error: Uncaught Error: Class 'Name\Hoge' not found in ...
これは Hoge がグローバル空間で宣言をされているためなので、以下のコード
class Hoge {
}
namespace Name;
class Foo {
}
$obj = new \Hoge();
var_dump($obj);
は正しく実行でき、結果は次のとおりとなる。
object(Hoge)#1 (0) {
}
選択肢2
名前空間は、namespace キーワードを使って宣言する。
また、名前空間はディレクトリやファイルと同様に、名前空間の階層構造を指定することができる。
そのため、以下のコード
namespace Name\SubName;
class Hoge {
}
$obj = new Hoge();
var_dump($obj);
を実行すると、結果は次のとおりとなる。
object(Name\SubName\Hoge)#1 (0) {
}
選択肢3
名前空間の定義がない場合、すべてのクラスや関数の定義はグローバル空間に配置される。PHPで定義済みのクラスも、グローバル空間に配置される。
先頭に \ (バックスラッシュ) を付けると、名前空間の内部からであってもグローバル空間の名前を指定することができる。
そのため、以下のコード
namespace Name;
try {
throw new Exception('error');
} catch (Exception $e) {
echo 'in to catch';
}
を実行すると、結果は次のとおりとなる。
Fatal error: Uncaught Error: Class "Name\Exception" not found in ...
一方で以下のコード
namespace Name;
try {
throw new \Exception('error');
} catch (\Exception $e) {
echo 'in to catch';
}
を実行すると in to catch となる。
選択肢4
PHPでのエイリアス作成には use 演算子を使用する。
use で指定する名前空間付きの名前の、先頭の \ (バックスラッシュ) は不要で、推奨されない。
そのため、以下のコード
namespace Name;
class Hoge {
}
class Foo {
}
namespace Name\Sub;
// よく使われているuse
use Name\Hoge;
$obj = new Hoge();
var_dump(__NAMESPACE__, $obj);
namespace Name\Sub2;
// エイリアスを定義したuse
use \Name\Hoge as Bar; // 先頭の \ は推奨されていない
echo PHP_EOL;
$obj = new Bar();
var_dump(__NAMESPACE__, $obj);
namespace Name\Sub3;
// useのグループ化
use Name\{Hoge, Foo};
echo PHP_EOL;
$hoge_obj = new Hoge();
$foo_obj = new Foo();
var_dump(__NAMESPACE__, $hoge_obj, $foo_obj);
は正しく実行でき、結果は次のとおりとなる。
string(8) "Name\Sub"
object(Name\Hoge)#1 (0) {
}
string(9) "Name\Sub2"
object(Name\Hoge)#2 (0) {
}
string(9) "Name\Sub3"
object(Name\Hoge)#1 (0) {
}
object(Name\Foo)#3 (0) {
}
回答と解説
問題は「名前空間」についてです。
公式マニュアルの「名前空間」のページを読んでおきましょう。
https://www.php.net/manual/ja/language.namespaces.php
選択肢1を見ていきましょう。
名前空間は、namespace キーワードを使って宣言します。
また、名前空間の宣言は、declare キーワード以外の他のコードより前にファイルの先頭で宣言をする必要があります。
名前空間の宣言前にクラスの定義などを書くことはできません。
そのため、選択肢にあるコードはいずれも「名前空間の宣言よりも前にクラスの定義が書いてある」ため、
Fatal error: Namespace declaration statement has to be the very first
statement or after any declare call in the script in ...
というエラーになります。
したがってこの選択肢には誤りがあります。
選択肢2を見ていきましょう。
マニュアルの「サブ名前空間の宣言」にあるとおりなのですが。
https://www.php.net/manual/ja/language.namespaces.nested.php
ディレクトリやファイルと同様、PHP の名前空間においても名前空間の階層構造を指定することができます。
階層構造の区切りには、バックスラッシュ(\)が用いられます。
したがってこの選択肢には正しいことが書かれています。
選択肢3を見ていきましょう。
名前空間の定義がない場合、すべてのクラスや関数の定義はグローバル空間に配置されます。
https://www.php.net/manual/ja/language.namespaces.global.php
これにはPHPで定義済みのクラスも含まれます。
また、先頭に\ (バックスラッシュ)を付けると、名前空間の内部からであってもグローバル空間の名前を指定することができます。
そのため、例えばPHPで定義済みのクラス Exception を、名前空間を宣言している中で使おうとすると、「宣言されている名前空間\Exception」と見なされます。
一方で、 \Exception と書くと、これは「グローバル空間の Exception」と見なされます。
したがってこの選択肢には正しいことが書かれています。
選択肢4を見ていきましょう。
PHPでのエイリアス作成には use 演算子を使用します。
https://www.php.net/manual/ja/language.namespaces.importing.php
クラスのエイリアスを切る場合、よく使われる書き方としては以下があります。use 名前空間\クラス名;
クラス名に別名をつけたい場合は、以下のように書くこともできます。use 名前空間\クラス名 as クラス別名;
グローバルクラスをuseする時は、このように書きます。use ArrayObject;
いずれも、名前空間の先頭のバックスラッシュは「不要」かつ「推奨されない」ので、覚えておきましょう。
また、同じ namespace から複数のクラス、関数、定数をインポートする際には、それらをひとつの use にまとめることができます。
https://www.php.net/manual/ja/language.namespaces.importing.php#language.namespaces.importing.group
したがってこの選択肢には正しいことが書かれています。
選択肢1に誤りがあるため、解答は1になります。
PHP8上級試験と公式問題集に興味がある方は、以下のページをご覧のうえ、この機会に是非受験ください。
PHP8上級試験
https://www.phpexam.jp/summary/expert8
公式問題集:PHP8技術者認定上級試験公式問題集上巻
https://www.amazon.co.jp/dp/B0FQ1LTTQ4/
公式問題集:PHP8技術者認定上級試験公式問題集下巻ベータ
https://www.amazon.co.jp/dp/B0F7F4H8FP/
また、試験対策セミナーは毎月開催しています。興味がある方は以下のページをご覧いただき是非セミナーにもご参加ください。(フォローいただけるとセミナーのご案内が届くようになります)
PHP技術者認定機構の公式Peatixグループ
https://peatix.com/group/43424
www.phpexam.jp

