
PHP8 上級/準上級試験の認定模擬問題として、プライム・ストラテジー様のPRIME STUDYが認定されているようです。ただ、この模擬問題には解説がありませんので解説をまとめていこうと思います。シリーズ第26回目です。

PHP初級レベルから脱却して中級/上級レベルにいきたい人にピッタリの内容ですね。

今回は文字列処理やエンコーディング、文字コードに関する関数の挙動を問う問題です。
PHPでの文字列処理は実務でもよく使われる知識なので、この機会に基本的な挙動をしっかり押さえていきましょう。
PRIME STUDY認定模擬問題のリンクはこちらです → https://study.prime-strategy.co.jp/
問題文
関数 に関する説明の中で、誤っているものを1つ選びなさい。
なお「\」はバックスラッシュに読み替えること。
また、すべてのコードには下記のコードが適切な箇所に書かれているものとする。
declare(strict_types=1);
error_reporting(-1);
下記はマニュアルから一部引用した内容である。
htmlentities ( string $string , int $flags = ENT_COMPAT , string|null $encoding = null , bool $double_encode = true ) : string
htmlspecialchars ( string $string , int $flags = ENT_COMPAT , string|null $encoding = null , bool $double_encode = true ) : string
ENT_COMPAT ダブルクオートは変換しますがシングルクオートは変換しません。
ENT_QUOTES シングルクオートとダブルクオートを共に変換します。
ENT_NOQUOTES シングルクオートとダブルクオートは共に変換されません。
trim ( string $string , string $characters = ” \n\r\t\v\0″ ) : string
ltrim ( string $string , string $characters = ” \n\r\t\v\0″ ) : string
rtrim ( string $string , string $characters = ” \n\r\t\v\0″ ) : string
strpos ( string $haystack , string $needle , int $offset = 0 ) : int|false
文字列 haystack の中で、 needle が最初に現れる位置を探します。
返り値
needle が見つかった位置を、 haystack 文字列の先頭 (offset の値とは無関係) からの相対位置で返します。 文字列の開始位置は 0 であり、1 ではないことに注意しましょう。
needle が見つからない場合は false を返します。
(1)
htmlentities() 関数と htmlspecialchars() 関数は、いずれも「文字を HTML エンティティに変換する」。
htmlspecialchars() 関数が「特殊文字」だけであるのに対し、htmlentities() 関数は「適用可能な全ての文字」を変換する。
この関数は、XSS 対策のためのエスケープ処理としてよく使われている。XSS 対策で使う場合、どちらを使ってもよい。
第二引数をデフォルトのままにすると「ダブルクオートは変換するがシングルクオートは変換しない」ので、XSS 対策用には、第二引数を ENT_QUOTES にするとよい。
そのため、以下のコード
$string = '<>&"\'∞';
echo $string, PHP_EOL;
echo htmlspecialchars($string), PHP_EOL;
echo htmlspecialchars($string, ENT_QUOTES), PHP_EOL;
echo htmlentities($string, ENT_QUOTES), PHP_EOL;
を実行すると、結果は次のとおりとなる。
<>&"'∞
<>&"'∞
<>&"'∞
<>&"'∞
(2)
trim() 関数は文字列の先頭および末尾にあるホワイトスペースを取り除く。
また、 文字列の最初から空白 (もしくはその他の文字) を取り除く ltrim() 関数、文字列の最後から空白 (もしくはその他の文字) を取り除く rtrim() 関数もある。
第二引数を指定しない場合は 0x20の空白、0x09のタブ、0x0Aのリターン などが削除されるが、引数を指定すると削除したい文字を指定する事も出来る。
そのため、以下のコード
$string = "\t a b\tc\n";
var_dump( trim($string) );
var_dump( trim($string, "\t\n ac") );
を実行すると、結果は次のとおりとなる。
string(5) "a b c"
string(1) "b"
(3)
ord() 関数は、文字列の先頭バイトを、0 から 255 までの値に変換する。
また chr() 関数は、数値から、1 バイトの文字列を生成する。
そのため、以下のコード
$s = 'abc';
$ascii = ord($s);
var_dump($ascii);
var_dump( chr($ascii) );
$ascii += 5;
var_dump( chr($ascii) );
を実行すると、結果は次のとおりとなる。
int(97)
string(1) "a"
string(1) "f"
(4)
strpos() 関数は文字列内の部分文字列が最初に現れる場所を見つける。
そのため、以下のコード
$fn = function($needle) {
$string = 'abc';
if ( strpos($string, $needle) != false ) {
echo "{$needle} が見つかりました", PHP_EOL;
} else {
echo "{$needle} は見つかりませんでした", PHP_EOL;
}
};
$fn('a');
$fn('z');
を実行すると、結果は次のとおりとなる。
a が見つかりました
z は見つかりませんでした
解説
選択肢1の解説
正解です。
一見、正しく見える内容ですが 出力結果の説明が間違っています。
$string = '<>&"\'∞';
echo $string, PHP_EOL;
echo htmlspecialchars($string), PHP_EOL;
echo htmlspecialchars($string, ENT_QUOTES), PHP_EOL;
echo htmlentities($string, ENT_QUOTES), PHP_EOL;
このコードを順に見ていくと…
(1行目)文字列の出力: <>&”‘∞ がそのまま表示されます。
(2行目)htmlspecialchars($string):第二引数を指定していないので、デフォルトの ENT_COMPAT が使われます。
(3行目)htmlspecialchars($string, ENT_QUOTES):第二引数にENT_QUOTESを指定しています。
(4行目)htmlentities($string, ENT_QUOTES):使える限りすべての文字をエンティティに変換します。
選択肢2の解説
正しいです。
trim() は文字列の 前後 の不要な文字を取り除く関数です。デフォルトでは \t(タブ)や \n(改行)、空白などを削除します。第二引数で削除したい文字を 個別に指定することもできます。
$string = "\t a b\tc\n";
この文字列は、前にタブ \t、後ろに改行 \n などが含まれています。このため、trim($string) の結果は “a b c”となります(先頭と末尾の制御文字が除かれる)。
trim($string, “\t\n ac”) は「\t・\n・空白・a・c」などを 先頭・末尾から削除され、中央の b だけが残ります。
よって出力結果は下記となります。
string(5) "a b c"
string(1) "b"
選択肢3の解説
正しいです。
ord() は文字列の最初の1文字を ASCII数値に変換します。
ord(‘a’) → 97(a の ASCII コード)
chr(97) → ‘a’(数値 → 文字)
chr(97 + 5) → chr(102) → ‘f’
このように、ASCII コードと文字の変換が可能です。
選択肢4の解説
誤りです。
このコードは一見正しそうに見えますが、strpos() の判定方法が間違っています。
if ( strpos($string, $needle) != false ) {
この判定だと、needle が先頭(位置 0)にある場合に 0 != false が false とみなされてしまうため、見つかっているのに見つかっていないと誤判定されます。
PHPでは、strpos() の返り値が 整数 0(先頭で見つかった)でも、それは false と同じように評価されてしまうため、=== を使って厳密比較する必要があります。
if ( strpos($string, $needle) !== false ) {
これが正しい書き方となります。
正解選択肢
以上より選択肢4が正解となります。
他の問題へ
模擬問題(1)インストール
模擬問題(2)変数の型
模擬問題(3)クラス
模擬問題(4)メソッドその1
模擬問題(5)メソッドその2
模擬問題(6)リファレンス
模擬問題(7)名前空間
模擬問題(8)エラー
模擬問題(9)定義済みのインターフェイスとクラスおよび SPL インターフェイス
模擬問題(10)SPL
模擬問題(11)定義済の変数
模擬問題(12)PHP7.0.xからPHP7.1.xへの移行
模擬問題(13)可変変数
模擬問題(14)PHP7.3.xからPHP7.4.xへの移行
模擬問題(15)PHP7.4.xからPHP8.0.xへの移行
模擬問題(16)制御構造
模擬問題(17)XSS(クロスサイトスクリプティング)
模擬問題(18)ファイルアップロード
模擬問題(19)推測困難なトークン
模擬問題(20)セッション
模擬問題(21)PHP のメモリ消費
模擬問題(22)関数その1
模擬問題(23)関数その2
模擬問題(24)関数その3
模擬問題(25)関数その4
模擬問題(26)関数その5
模擬問題(27)関数その6
模擬問題(28)関数その7
模擬問題(29)関数その8
模擬問題(30)関数その9
コメント