難易度は Level 1(やさしめ)〜Level 5(難関) の5段階です。
PHP8 技術者認定 上級/準上級のサンプル問題(本番形式・解説付き)
PHP8 技術者認定 上級/準上級(PHP技術者認定機構・PHP8技術者認定上級/準上級試験(PHP 8.0 対象・主教材 PHP マニュアル))の出題形式を、実際の問題で確かめられます。ここに掲載する5問は、無料の会員登録で解ける模試 第1回(30問)の冒頭から抜粋したオリジナル問題です。当サイトは全120問を本番CBT準拠の形式で収録しており、この5問はそのごく一部にあたります。
設問1
PHP 8.0 で次のコードを実行した時の出力として、正しいものはどれですか。 ```php var_dump(0 == "abc", "1" == "01", "10" == "1e1", 100 == "1e2"); ```
- `false`、`true`、`true`、`true`(正解)
- `false`、`false`、`false`、`true`
- `true`、`false`、`true`、`false`
- `true`、`true`、`true`、`true`
解説
PHP 8.0 では、数値と非数値の文字列を比べると、数値を文字列に直して文字列同士で比べます。`0 == "abc"` は `"0" == "abc"` となり `false` です。数値文字列同士は数値として比べるので、`"1" == "01"`、`"10" == "1e1"` は `true` で、数値と数値文字列の `100 == "1e2"` も `true` です。1 つ目を `true` とするのは PHP 7 以前の挙動で、`"abc"` が 0 に変換されていました。`"1" == "01"` と `"10" == "1e1"` を `false` とするのは、文字列として比べるという誤解です。`100 == "1e2"` は指数表記も数値として解釈されるため `true` で、4 つ目を `false` とするのも誤りです。
設問2
PHP 8.0 で次のコードを実行した時、出力として正しいものはどれですか。 ```php var_dump(str_contains("abc", "")); ```
- Warning が出たうえで bool(false) が出力される
- ValueError が投げられ、処理が中断する
- bool(false)
- bool(true)(正解)
解説
`str_contains()` は PHP 8.0 で追加された関数で、探す文字列が空文字列の場合は常に true を返します。空文字列は、どの文字列にも先頭位置で含まれると扱われるためです。false になるのは、探す文字列が実際に含まれていない場合だけです。空文字列の針は ValueError の対象ではありません(ValueError になるのは `explode()` の区切り文字が空の場合などです)。警告も出ず、true が返ります。
設問3
PHP 8.0 で次のコードを実行した時の出力として、正しいものはどれですか。 ```php var_dump(null == false, 0 == "", "0" == false, "" == null); ```
- `false`、`false`、`true`、`true`
- `true`、`false`、`true`、`true`(正解)
- `true`、`true`、`true`、`true`
- `true`、`false`、`false`、`true`
解説
`null == false` は、どちらも真偽値として見ると `false` 同士なので `true` です。`0 == ""` は、空文字列が数値ではないため 0 を文字列 `"0"` に直して比べ、`false` になります。`"0" == false` は文字列を真偽値に直すと `false` になるので `true`、`"" == null` も `true` です。2 つ目を `true` とするのは PHP 7 以前の挙動です。`null == false` を `false` とするのは、`null` と真偽値のゆるい比較を取り違えた誤りです。`"0" == false` を `false` とするのは、`"0"` が真偽値では `false` になる規則を忘れた誤りです。
設問4
次のコードを PHP 8.0 で実行する Web ページがあります。`$name` に `x' onmouseover='alert(1)` が入った時、XSS が成立してしまう理由として、正しいものはどれですか。 ```php echo "<input value='" . htmlspecialchars($name) . "'>"; ```
- 既定では `<` と `>` が変換されないため、新しいタグを挿入できるため
- フラグを省略した時の既定では単一引用符が変換されず、属性値を `'` で閉じて別の属性を挿入できるため(正解)
- UTF-8 の文字列は htmlspecialchars の変換の対象外のため、値がそのまま出力されるため
- 既定では二重引用符が変換されないため、値の途中の `"` でタグを閉じられるため
解説
PHP 8.0 の htmlspecialchars の既定のフラグは `ENT_COMPAT | ENT_HTML401` で、二重引用符は変換されますが単一引用符は変換されません。値を `'` で囲んだ属性では、入力中の `'` で属性を閉じて `onmouseover` などを挿入できます。`ENT_QUOTES` を指定すれば単一引用符も `'` に変換されます。二重引用符は既定でも `"` に変換されます。`<` と `>` も既定で変換されます。文字種にかかわらず特殊文字は変換されます。なお、不正な UTF-8 の文字列は ENT_SUBSTITUTE を付けない限り空文字列になります。
設問5
PHP 8.0 で次のコードを実行した時の動作として、正しいものはどれですか。 ```php $r = "abc" * 1; ```
- 警告なしで、`$r` は `0` になる
- 警告が出て、`$r` は `0` になる
- `TypeError` の例外となり、`$r` には何も代入されない(正解)
- `$r` は文字列 `"abc"` のまま変わらない
解説
PHP 8.0 では、数値として解釈できない文字列を算術演算の被演算子にすると `TypeError`(`Unsupported operand types`)が投げられます。警告を出して 0 として計算を続けるのは、PHP 7.1〜7.4 の挙動です。警告も出さずに 0 になるのは PHP 7.0 以前の挙動で、8.0 では例外になります。乗算の結果が元の文字列のままになることもなく、演算は必ず数値を返すか例外になります。
続きは、会員登録なしでそのまま50問解けます。採点と解説つきで、上と同じ本物の問題です。
登録なしで50問解く