• PHP
【php8上級/準上級試験】模擬問題解説 問題10. SPL RecursiveDirectoryIterator RecursiveIteratorIterator SplFileInfo SplFileObject

「第1回 PHP 8 上級 模擬試験」を解説していきます

本記事ではひたすら下記記事の模擬試験の解説をしていきたいと思います!

第1回 PHP 8 上級 模擬試験
https://study.prime-strategy.co.jp/study/ph8ex1/

解説記事一覧

模擬問題 10

SPL に関する説明の中で、誤っているものを1つ選びなさい。
なお、すべてのコードの先頭には下記のコードが書かれているものとする。

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

RecursiveDirectoryIterator クラスは、ファイルシステムのディレクトリを再帰的に反復処理するためのクラスである。
RecursiveDirectoryIterator クラスのオブジェクトをRecursiveIteratorIterator クラスで処理する事によって、RecursiveIteratorIterator クラスが「再帰的なイテレータの反復処理をする」ために、ファイルシステムのディレクトリを再帰的に反復処理する事が出来るようになる。
そのため、以下のコード

$dir = new RecursiveIteratorIterator(
           new RecursiveDirectoryIterator(__DIR__)
);

while($dir->valid()) {
    echo $dir->getPathname(), PHP_EOL;
    $dir->next();
}

は正しく実行でき、結果は次のような結果を得ることができる。

/home/phpexam/phpexam/.
/home/phpexam/phpexam/..
/home/phpexam/phpexam/dir/.
/home/phpexam/phpexam/dir/..
/home/phpexam/phpexam/dir/test
/home/phpexam/phpexam/sample.php

SPL(Standard PHP Library)とは?

SPL(Standard PHP Library)は、PHPに 標準で組み込まれているライブラリで、便利なクラスやインターフェースの集まりです

コードでは SPL(Standard PHP Library) のクラスを 2つ 使用しています。

  1. RecursiveDirectoryIterator(再帰的にフォルダ内のファイルを取得)
  2. RecursiveIteratorIterator(RecursiveDirectoryIterator の結果を1つのリストのように扱う)

この2つを組み合わせることで、サブフォルダ内のファイルまで 自動的に探索 できるようになっています。

RecursiveIteratorIterator RecursiveDirectoryIterator フォルダ サブフォルダ ファイル1 ファイル2 ファイル3 利用 走査 含む 含む 含む 含む

つまり、「2重にインスタンス化 していることで、ディレクトリ構造を 深くたどれるようになっている」ということです!

よって選択肢は正解⭕です

SplFileInfo クラスは、ファイルの情報取得のためのクラスである。
単純にファイル名や拡張子の他、inode 番号や inode 変更時刻、ファイルの所有者など、様々な情報を得る事ができるほか、SplFileObject クラスと同様のファイル操作も行う事ができる。
そのため、以下のコード

$file_info = new SplFileInfo(__FILE__);
echo $file_info->getFilename(), PHP_EOL;
echo $file_info->getInode(), PHP_EOL;
echo $file_info->fread(9999), PHP_EOL;

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

sample.php
40318019
declare(strict_types=1);
error_reporting(-1);
$file_info = new SplFileInfo(__FILE__);
echo $file_info->getFilename(), PHP_EOL;
echo $file_info->getInode(), PHP_EOL;
echo $file_info->fread(9999), PHP_EOL;

SplFileInfo クラス

SplFileInfo クラスは、ファイルの詳細情報を取得するためのPHPのクラスです。
普通のファイル名や拡張子だけでなく、inode番号(ファイルの一意なID)や最終更新時刻、所有者などの詳細情報を取得できます。

📄 sample.php 🗂️ SplFileInfo 📛 getFilename(): sample.php 🔢 getInode(): 40318019

SplFileInfo は「ファイル情報を取得するクラス」であり、ファイル操作はできない

誤り:
SplFileInfo クラスは、SplFileObject クラスと同様のファイル操作も行う事ができる。

SplFileInfo はファイルの 名前・拡張子・サイズ・パーミッション などの情報を取得できるが、fread() のような読み込みはできない。

echo $file_info->fread(9999), PHP_EOL;

//出力結果
PHP Fatal error:  Uncaught Error: Call to undefined method SplFileInfo::fread()

上記より選択肢は正解❌です

SplFileObject クラスは、ファイルのためのオブジェクト指向のインターフェイスを提供する。
ファイルへの書き込みや読み込み、seek() メソッドでのファイルポインタの移動なども行うことができる。
そのため、以下のコード

$file = new SplFileObject(__FILE__);

while($line = $file->fgets()) {
    echo $line;
}

echo 'fin';

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

$file = new SplFileObject(__FILE__);

while($line = $file->fgets()) {
    echo $line;
}

echo 'fin';
fin

SplFileObject

SplFileObjectはファイル操作のための専用クラスです。

主な特徴:

  • ファイルの読み書きが簡単
  • 1行ずつの読み込みが可能
  • ファイル内の位置移動ができる
  • イテレータとして使える

オブジェクト指向のファイル操作

// 従来の方法(手続き型)

$file = new SplFileObject("test.txt");
while($line = $file->fgets()) {
    echo $line;  // 1行ずつ読み込み
}
// オブジェクト指向(SplFileObject)

$file = new SplFileObject("test.txt");
$file->fgets();
// closeは自動
手続き型 ファイル fopen() fgets() fclose() オブジェクト指向 SplFileObject ファイルデータ fgets() seek() その他のメソッド

よって選択肢の内容は正解⭕です。

SplTempFileObject クラスは、一時ファイルのためのオブジェクト指向のインターフェイスを提供する。
一時ファイルは「メモリまたはテンポラリファイル」上に作成される。
そのため、以下のコード

$file = new SplTempFileObject();
echo $file->getPathname();

を実行すると php://temp となる。

SplTempFileObject

SplTempFileObject は SplFileObject を継承(派生クラス)しており、一時ファイルを扱うためのクラスです

基本的なSplTempFileObjectの使用方法

// メモリ上に一時ファイルを作成
$file = new SplTempFileObject();
new SplTempFileObject(); 一時ファイル作成
//  一時ファイルに "Hello, World!" を書き込む
$file->fwrite("Hello, World!\n");
$file->rewind(); echo $file->fgets(); データを読み込む

getPathname() が php://temp を返す理由

💡 getPathname() は「開いているファイルの名前」を返すメソッド です。
💡 SplTempFileObject は 実際のファイルを作らず、メモリ上の特別な領域 (php://temp) にデータを保存 します。
💡 だから、getPathname() を呼ぶと php://temp になるのです。

データ保存: php://temp メモリ上で管理(2MB以下)

よって選択肢の内容は正解⭕です。

問題番号正解の選択肢
1PHPの「最新以外の(古い)コード」は、公式サイトでの提供は全くしていない。そのため、古いバージョンのコードが必要な場合、別途「非公式の外部サイト」からソースコードを入手する必要がある。
2論理型 (boolean) は「真偽値」とも呼ばれ、値は true か false か null のいずれかになる。なお、true、false、null の文字は、大文字でも小文字でもよい。
3抽象クラスから継承する際、親クラスで abstract としてマークされた全てのメソッドは子クラスで定義する必要があり、可視性は同等(またはより緩い制約)で、必須引数の数は同じであれば型宣言が異なってもかまわない。
4PHP において、デストラクタは __destruct() メソッドで実装される。親クラスのデストラクタは暗黙的に呼ばれ、呼び出し順序は「子クラスのデストラクタ → 親クラスのデストラクタ」となる。
5__get() はアクセス不能(protected または private)または存在しないプロパティからデータを読み込む際に使用される。なお、__getStatic() は存在せず、オブジェクトや静的コンテキストで動作しない。
6PHP のリファレンス渡しを使用すると、関数内で引数を修正できる。(※※正解テキストでは「呼び出す側で変数に & を付ける必要がある」と記載されています。)
7名前空間は namespace キーワードで宣言する。通常はファイルの先頭に記述する必要があり、名前空間宣言前に書かれたクラスはその名前空間に含まれない。
8PHP 5 では Exception クラスが全例外の基底クラスだったが、PHP 7 以降は Exception クラスは Throwable インタフェースを基底とし、Error クラスが内部エラーの基底クラスとして導入された。
9ArrayAccess インターフェイスは、オブジェクトを配列としてアクセスするための機能を提供する。
10SplFileInfo クラスは、ファイルの情報取得や操作を行うためのクラスである。
11$_COOKIE は、HTTP クッキーから渡された値が連想配列として格納され、また設定も可能である。
12PHP 7.1.x では、文字列操作関数で負のオフセット指定が可能となり、[] や {} による文字単位のアクセスも文字列の末尾からのオフセットとして解釈される。
13可変変数は、スーパーグローバル変数にも使用できる。
14PHP 7.4.x では、波括弧を使った配列や文字列のオフセットアクセスの文法は非推奨となった。
15PHP 8 では、private メソッドの継承に関するルールが変更され、親クラスの同名メソッドの可視性に関係なく子クラスでオーバーライド可能となった。
16break は、現在実行中の for, foreach, while, do-while, switch 構造の実行を終了し、オプションでネストしたループの何段分を抜けるか指定できる。
17XSS 対策として、htmlentities() を適切に使用することで、文字列や配列の入力に対して安全な出力が可能となる。
18アップロードされたファイルの元のファイル名は、$_FILES[‘{formのnameの値}’][‘name’] に格納され、move_uploaded_file() の第二引数として利用できる。
19uniqid() と mt_rand() を組み合わせることで、暗号論的にランダムな(推測困難な)トークンを生成できる。
20PHP のセッションでは、セッション ID がクッキーに保存され、session_set_cookie_params() によりそのクッキーのパラメータを設定できる。
21PHP の変数の参照カウントは、xdebug_debug_zval() で確認でき、オブジェクトを clone した場合は内部的に参照が使われ、一時的に参照カウントが増加する。
22DirectoryIterator クラスは、ディレクトリ内のファイルやサブディレクトリの情報を取得するシンプルなインターフェイスを提供する。
23mail() 関数は、メールを送信するための関数で、第四引数で追加のヘッダー情報を指定できる。
24escapeshellarg() と escapeshellcmd() は、外部入力をシェルコマンドの引数として使用する際に必要なエスケープ処理を行い、どちらを使用しても意味合いは同じである。
25stream_wrapper_register() 関数を使用すると、新しいストリームラッパー(プロトコルハンドラ)を登録できるが、既に存在する場合は失敗する。
26strpos() 関数は、文字列内で指定した部分文字列の最初の出現位置を返し、見つからなければ false を返す。ただし、先頭位置の場合は 0 が返るため注意が必要。
27Phar のスタブには __HALT_COMPILER() が使用され、これ以降のコードはコンパイルされない。
28function_exists() 関数は、指定された関数が定義されているかどうかをチェックし、存在すれば true を返す。
29openssl_decrypt() 関数は、openssl_encrypt() で暗号化されたデータを正しく復号し、元のデータを取り戻す。
30strtotime() 関数は、英語形式の日付文字列を Unix タイムスタンプに変換し、無効な日付の場合は false を返す。