[模擬問題] PHP8上級 – PHP7.1(CTO古庄道明からの出題)

こんにちは。PHP技術者認定機構 CTOの古庄道明です。
今日もPHP8上級試験の模擬問題と解説を紹介します。
以下を解いて出題のイメージと知識を補っていただけると幸いです。

目次

問題

PHP 7.0.x から PHP 7.1.x への移行 に関する説明の中で、誤っているものを1つ選びなさい。
なお、この設問のコードの実行結果はPHP 7.1.xで実行した場合のものとし、すべてのコードの先頭には下記のコードが書かれているものとする。

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

選択肢

選択肢1
配列の短縮構文 ([]) を使って、 代入用に配列の値を取り出せるようになった。
これは、list() の代替として使うことができる(list() が無くなったわけではない)。
そのため、以下のコード

$data = [
    [1, 2],
    [777, 999],
];

list($i, $j) = $data[0];
var_dump($i, $j);
[$i, $j] = $data[1];
var_dump($i, $j);

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

int(1)
int(2)
int(777)
int(999)

選択肢2
新しい擬似型 (callable と同じような型) である iterable が導入された。パラメータおよび返り値の型指定で使うことができ、「配列か、あるいは Traversable イン
ターフェイスを実装したオブジェクトを受け付ける」ようになる。そのため、以下のコード

function hoge(iterable $itr) {
    var_dump($itr);
}

hoge([1, 2]);
hoge(new ArrayObject());

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

array(2) {
  [0]=>
  int(1)
  [1]=>
  int(2)
}
object(ArrayObject)#1 (1) {
  ["storage":"ArrayObject":private]=>
  array(0) {
  }
}

一方で以下のコード

function hoge(iterable $itr) {
    var_dump($itr);
}

$obj = new stdClass();
$obj->s = 'string';
$obj->i = 999;
hoge($obj);

を実行すると、結果は次のとおりとなる。

Fatal error: Uncaught TypeError: Argument 1 passed to hoge() must be iterable, object given, called in ...

選択肢3
数値形式ではない文字列を使って、数値を期待する演算 (+, -, *, /, **, %, <<, >>, |, &, ^ や、これらを用いた代入演算) を行おうとしたときに、 E_WARNING あるいは E_NOTICE レベルのエラーが発生するようになった。
そのため、以下のコード

$i = '11' + '22';
var_dump($i);

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

int(33)

一方で以下のコード

$i = '11' + 'a';
var_dump($i);

を実行すると、結果は次のとおりとなる。

Warning: A non-numeric value encountered in ...
int(11)

選択肢4
文字列操作関数のうちオフセット指定のできるものすべてについて、負のオフセットを指定できるようになった。
[] や {} による文字列への文字単位のアクセス についても同様となり、負のオフセットは、文字列の末尾からのオフセットと解釈される。
負の値を渡した場合、-0 が「文字列の末尾」となる。そのため、以下のコード

$s = 'abcdefg';
var_dump( $s[-1] );

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

string(1) "f"

回答と解説

問題は「PHP7.1」についてです。
公式マニュアルの「PHP 7.0.x から PHP 7.1.x への移行」のページを読んでおきましょう。
https://www.php.net/manual/ja/migration71.php

選択肢1を見ていきましょう。
配列の短縮構文 ([]) を使って、 代入用に配列の値を取り出せるようになりました。
https://www.php.net/manual/ja/migration71.new-features.php#migration71.new-features.symmetric-array-destructuring

list($i, $j) = $data[0];
var_dump($i, $j);

は従来から動くコードで、今回のコードの場合は $data[0] には [1, 2] が入っているため、$iには1が、$jには2が代入されます。

[$i, $j] = $data[1];
var_dump($i, $j);

が新しくできるようになったコードで、今回のコードの場合は $data[1] には[777, 999] が入っているため、$iには777が、$jには999が代入されます。

したがってこの選択肢には正しいことが書かれています。

選択肢2を見ていきましょう。
新しい擬似型 (callable と同じような型) である iterable が導入されました。
https://www.php.net/manual/ja/migration71.new-features.php#migration71.new-features.iterable-pseudo-type

パラメータおよび返り値の型指定で使うことができ、「配列か、あるいは Traversable インターフェイスを実装したオブジェクトを受け付ける」ようになります。
例題にある

function hoge(iterable $itr) {
    var_dump($itr);
}

のとき、

hoge([1, 2]);

は「配列」であるため正しく動き、また

hoge(new ArrayObject());

は、ArrayObject が IteratorAggregate インターフェイスを実装しており、IteratorAggregate は Traversable を継承しているため、正しく動きます。

一方で

$obj = new stdClass();
$obj->s = 'string';
$obj->i = 999;
hoge($obj);

の場合、stdClass() はTraversable インターフェイスを実装していないため、TypeErrorとなります。

したがってこの選択肢には正しいことが書かれています。

選択肢3を見ていきましょう。
数値形式ではない文字列を使って、数値を期待する演算 (+, -, *, /, **, %, <<,>>, |, &, ^ や、これらを用いた代入演算) を行おうとしたときに、 E_WARNING あるいは E_NOTICE レベルのエラーが発生するようになりました。
https://www.php.net/manual/ja/migration71.other-changes.php#migration71.other-changes.apprise-on-arithmetic-with-invalid-strings

「数値形式の文字列」であれば問題なく演算ができる点に注意しましょう。

そのため、例題のうち

$i = '11' + '22';
var_dump($i);

これは「数値形式の文字列」のため問題なく演算ができ、一方で

$i = '11' + 'a';
var_dump($i);

は「数値形式ではない文字列」のため、Warningが発生します。

したがってこの選択肢には正しいことが書かれています。

なお、このコードをPHP8.0以降で実行すると、TypeErrorとなります。
PHP7系ではWarningが発生しても演算が継続されていたコードが、PHP8ではTypeErrorによって処理が中断されることがあります。
PHP7系からPHP8への移行時には注意しましょう。

選択肢4を見ていきましょう。
文字列操作関数のうちオフセット指定のできるものすべてについて、負のオフセットを指定できるようになりました。
https://www.php.net/manual/ja/migration71.new-features.php#migration71.new-features.support-for-negative-string-offsets

負のオフセットは、文字列の末尾からのオフセットと解釈されます。
ただし、負の整数は -1 以下であり、整数の -0 は 0 と同じ値になります。
そのため、-0 を指定しても文字列の末尾を指すことにはならず、先頭の文字を指します。

そのため

$s = 'abcdefg';
var_dump( $s[-1] );

の実行は正しくできますが、結果は

string(1) "g"

となります。
したがってこの選択肢には誤りがあります。

なお、設問に「[] や {} による文字列への文字単位のアクセス」とありますが、{}によるアクセスはPHP8.0で削除されています。
PHPのコードで「7系で動かしている」ケースで、PHP8だと「動かなくなる」一因にもなり得るので、注意をしましょう。

選択肢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

この記事が気に入ったら
いいね または フォローしてね!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次