こんにちは。PHP技術者認定機構 CTOの古庄道明です。
今日もPHP8上級試験の模擬問題と解説を紹介します。
以下を解いて出題のイメージと知識を補っていただけると幸いです。
問題
定義済みの変数 に関する説明の中で、誤っているものを1つ選びなさい。
なお、すべてのコードの先頭には下記のコードが書かれているものとする。
declare(strict_types=1);
error_reporting(-1);
選択肢
選択肢1$_SERVER は、ヘッダ、パス、スクリプトの位置のような 情報を有する配列である。
この配列のエントリは Web サーバーにより生成されるため、PHP をコマンドラインで実行している場合には、使用できないものもある。
そのため、以下のコード
var_dump( $_SERVER['REMOTE_ADDR'] );
を Web サーバ経由で実行した場合は現在ページをみているユーザーの IP アドレスが出力されるが、コマンドラインから実行した場合は次のような結果となる。
Warning: Undefined array key "REMOTE_ADDR" in ...
NULL
選択肢2$GLOBALS はグローバルスコープで使用可能なすべての変数への参照である。変数名が配列のキーとなる。そのため、以下のコード
function hoge() {
var_dump( $GLOBALS['i'] );
}
$i = 999;
hoge();
は正しく実行でき、結果は次のとおりとなる。
int(999)
選択肢3$argv はスクリプトに渡された引数の配列である。(register_argc_argv が無効の場合は $argv は利用でき$argv[0] はスクリプトの実行に使う名前となり、$argv[1] 以降に引数の配列が入る。
そのため、
var_dump( $argv[1], $argv[2] );
上記のコードを
php sample.php aaa "bb cc dd" 999
のように呼び出すと、結果は次のとおりとなる。
string(3) "aaa"
string(8) "bb cc dd"
選択肢4$_COOKIE は現在のスクリプトに HTTP クッキーから渡された変数の連想配列である。
Cookie から渡された値は $_COOKIE に入り、また $_COOKIE に設定した値は Cookieとして設定される。そのため、以下のコード
$_COOKIE['i'] = ($_COOKIE['i'] ?? 0) + 1;
var_dump($_COOKIE['i']);
をブラウザから呼び出すと、
1回目の結果は次のとおりとなる。
int(1)
2回目の結果は次のとおりとなる。
int(2)
3回目の結果は次のとおりとなる。
int(3)
回答と解説
問題は「定義済みの変数」についてです。
公式マニュアルの「定義済みの変数」のページを読んでおきましょう。
https://www.php.net/manual/ja/reserved.variables.php
選択肢1を見ていきましょう。$_SERVER には、サーバー情報および実行時の環境情報が入っていて、この配列のエントリは、Web サーバーにより生成されます。
https://www.php.net/manual/ja/reserved.variables.server.php
この配列のエントリのうち、 REMOTE_ADDR は「現在ページをみているユーザーの IP アドレス」が入ります。
そのため、Webサーバ経由で実行された場合はユーザのIPアドレスが入りますが、コマンドラインから実行した場合は情報がないため、$_SERVER に REMOTE_ADDR のキーがそもそも存在しません。
そのため、PHP8における「その配列にキーがない状態でアクセスをした」場合の挙動である
- Warning: Undefined array key “REMOTE_ADDR” in … が出る
- null が返る
となります。
したがってこの選択肢には正しいことが書かれています。
なお、実務において「ロードバランサやプロキシを経由」している場合は、注意が必要な時があります。
ロードバランサ等の設定によるのですが、REMOTE_ADDRが「ロードバランサのIPである」可能性があります。
その場合、これも設定によるのですが、「X-Forwarded-For」というヘッダのほうに「アクセスしてきたユーザのIPアドレスが入っている」事があるので、気をつけておくとよいでしょう。
選択肢2を見ていきましょう。$GLOBALS は、グローバルスコープで使用可能なすべての変数への参照を含む連想配列です。
グローバルスコープの変数名が配列のキーとなります。
https://www.php.net/manual/ja/reserved.variables.globals.php
そのため、グローバルスコープに $i という変数がある場合、この変数は
$GLOBALS['i']
でアクセスが可能です。
故に、関数内での
var_dump( $GLOBALS['i'] );
のコードは、「グローバルスコープの $i をvar_dump()する」のと同じ意味合いになります。
したがってこの選択肢には正しいことが書かれています。
選択肢3を見ていきましょう。$argv には、コマンドラインから実行したときに、現在のスクリプトに渡されたすべての引数の配列が含まれます。
また、[0]は「スクリプトの実行に使う名前(自身のファイル名)」が入るため、与えられた引数は $argv[1] 以降に入ってきます。
https://www.php.net/manual/ja/reserved.variables.argv.php
コマンドライン上で引数をどのように区切るかは、使用しているシェルなどの環境にも依存します。一般的なシェルでは、スペースを含む文字列をダブルクォートで囲むことで、1つの引数として渡すことができます。
そのため
php sample.php aaa "bb cc dd" 999
と呼んだ場合、$argvの中を表記すると、以下のようになります。
$argv = [
0 => "sample.php",
1 => "aaa",
2 => "bb cc dd",
3 => "999",
];
そのため
var_dump( $argv[1], $argv[2] );
であれば
string(3) "aaa"
string(8) "bb cc dd"
となります。
したがってこの選択肢には正しいことが書かれています。
選択肢4を見ていきましょう。$_COOKIE は、現在のスクリプトに HTTP クッキーから渡された変数の連想配列です。
https://www.php.net/manual/ja/reserved.variables.cookies.php
HTTP クッキーは「key = value」の形をとるため、それがそのまま連想配列として $_COOKIE に入ってきます。
ただし、「$_COOKIE に設定した値は Cookie として設定され」ません。
Cookieの設定には、setcookie() や setrawcookie() などを使います。
https://www.php.net/manual/ja/function.setcookie.php
https://www.php.net/manual/ja/function.setrawcookie.php
そのため、例題のコードではCookieが設定できていないため、何度実行しても挙動としては
int(1)
が繰り返される動きになります。
したがってこの選択肢には誤りがあります。
選択肢4に誤りがあるため、解答は4になります。
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

