Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【PHP8.x】php_user_filter::paramsプロパティの使い方

paramsプロパティの使い方について、初心者にもわかりやすく解説します。

作成日: 更新日:

基本的な使い方

paramsプロパティは、php_user_filterクラスに属し、ユーザー定義のストリームフィルターに外部から渡される設定パラメータを保持するプロパティです。php_user_filterクラスは、PHPにおいてファイルやネットワークなどのデータストリームに独自の変換処理を適用するためのクラスです。

このプロパティには、stream_filter_append()関数などでフィルターをデータストリームに適用する際、オプションとして指定された文字列が、フィルターオブジェクト内部の$this->paramsに格納されます。

フィルターの実装者は、このparamsの値を読み取ることで、フィルターの動作を動的に変更したり、処理条件を設定したりできます。これにより、一つのフィルタークラスを異なる設定で柔軟に再利用でき、コードの汎用性向上に役立ちます。例えば、文字コード変換フィルターで、変換先の文字コードをparamsを通じて指定する、といった使い方です。paramsプロパティは通常mixed型ですが、多くは文字列として渡され、フィルター内で解析して使用されます。

構文(syntax)

1<?php
2class MyUserFilter extends php_user_filter
3{
4    public function filter($in, $out, &$consumed, $closing)
5    {
6        $this->params;
7
8        // ... フィルター処理のロジック ...
9
10        return PSFS_PASS_ON;
11    }
12}
13?>

引数(parameters)

引数なし

引数はありません

戻り値(return)

mixed

params プロパティは、ユーザー定義フィルターに渡された追加のパラメータを保持する混合型(mixed)の値を返します。

サンプルコード

PHP フィルタで params を利用する

1<?php
2
3/**
4 * php_user_filter を継承したカスタムストリームフィルタの例。
5 * このフィルタは、ストリーム処理時に渡されたパラメータ ($this->params) を利用し、
6 * データに特定の接頭辞と接尾辞を追加します。
7 */
8class MyParameterAwareFilter extends php_user_filter
9{
10    /**
11     * ストリームのフィルタ処理を実行します。
12     * このメソッド内で、$this->params プロパティにアクセスして、
13     * ストリームフィルタ登録時に渡されたパラメータを利用できます。
14     *
15     * @param resource $in 読み込み元のバケットブリッジ。フィルタリング対象のデータが含まれます。
16     * @param resource $out 書き込み先のバケットブリッジ。処理結果のデータを格納します。
17     * @param int $consumed 処理されたバイト数の合計。参照渡しで、このメソッド内で更新する必要があります。
18     * @param bool $closing ストリームが閉じられようとしているかどうかのフラグ。
19     * @return int フィルタリング結果を示す定数 (PSFS_PASS_ON, PSFS_FEED_ME, PSFS_ERR_FATAL)。
20     */
21    public function filter($in, $out, &$consumed, $closing)
22    {
23        echo "--- フィルタ処理開始 ---\n";
24        echo "フィルタ名: " . $this->filtername . "\n";
25
26        // $this->params プロパティは、stream_filter_append() や stream_filter_prepend() の
27        // 第4引数で渡された値が自動的に格納されます。
28        echo "渡されたパラメータ (params): \n";
29        var_dump($this->params);
30
31        $prefix = $this->params['prefix'] ?? '';
32        $suffix = $this->params['suffix'] ?? '';
33
34        while ($bucket = stream_bucket_make_writeable($in)) {
35            // パラメータに基づいてデータを変換
36            $processedData = $prefix . $bucket->data . $suffix;
37
38            $bucket->data = $processedData;
39            $bucket->datalen = strlen($processedData);
40
41            $consumed += $bucket->datalen;
42            stream_bucket_append($out, $bucket);
43        }
44
45        echo "--- フィルタ処理終了 ---\n\n";
46
47        // 処理を続行し、残りのデータを次のフィルタまたはストリームに渡します。
48        return PSFS_PASS_ON;
49    }
50}
51
52// 1. カスタムフィルタをPHPに登録します。
53// 'my_param_filter' という名前で MyParameterAwareFilter クラスを関連付けます。
54stream_filter_register('my_param_filter', MyParameterAwareFilter::class)
55    or die("フィルタの登録に失敗しました。\n");
56
57echo "フィルタ 'my_param_filter' が登録されました。\n\n";
58
59// 2. メモリ上に一時的なストリームを作成します。
60// これはファイルやネットワーク接続の代わりに、フィルタをテストするための仮想的なストリームです。
61$fp = fopen('php://memory', 'r+');
62
63if (!$fp) {
64    die("ストリームのオープンに失敗しました。\n");
65}
66
67echo "メモリ上のストリームを開きました。\n\n";
68
69// 3. フィルタをストリームにアタッチし、パラメータを渡します。
70// stream_filter_append() の第4引数に連想配列を渡すことで、
71// MyParameterAwareFilter クラス内の $this->params プロパティにその配列が格納されます。
72$filter = stream_filter_append($fp, 'my_param_filter', STREAM_FILTER_READ, [
73    'prefix' => '[START_LOG] ',
74    'suffix' => ' [END_LOG]',
75    'level' => 'INFO',
76    'timestamp' => date('Y-m-d H:i:s')
77]);
78
79if (!$filter) {
80    die("フィルタのストリームへの追加に失敗しました。\n");
81}
82
83echo "フィルタ 'my_param_filter' が指定されたパラメータと共にストリームに追加されました。\n\n";
84
85// 4. ストリームにデータを書き込み、フィルタ処理をトリガーします。
86$originalData = "ユーザーの操作ログデータ。";
87fwrite($fp, $originalData);
88
89// フィルタが書き込みではなく読み込み用に設定されているため、
90// データを読み出すときにフィルタが適用されます。
91// ストリームポインタを先頭に戻します。
92rewind($fp);
93
94// フィルタが適用されたデータを読み出します。
95$filteredData = stream_get_contents($fp);
96
97echo "--- 実行結果 ---\n";
98echo "元のデータ: " . $originalData . "\n";
99echo "フィルタ適用後のデータ: " . $filteredData . "\n\n";
100
101// 5. ストリームを閉じます。
102fclose($fp);
103echo "ストリームを閉じました。\n";

php_user_filter::paramsは、PHP 8のカスタムストリームフィルタ機能で利用される、php_user_filterクラスを継承したフィルタ内でアクセスできるプロパティです。このプロパティは、フィルタがストリームに登録または追加される際に、外部から渡された任意のオプションパラメータを保持する役割を持っています。具体的には、stream_filter_append()stream_filter_prepend()関数を使用する際、第4引数に指定された値がフィルタクラスのインスタンス内で$this->paramsプロパティとして自動的に格納されます。

フィルタクラスのfilterメソッド内で$this->paramsにアクセスすることで、フィルタの処理内容を動的に制御したり、外部から与えられた設定値に基づいて振る舞いを変更したりすることが可能です。このプロパティの戻り値の型はmixedとされており、これは渡されるパラメータが文字列、数値、配列など、さまざまなデータ型を取りうることを示しますが、実用上は連想配列として使われることが一般的です。

サンプルコードでは、MyParameterAwareFilterというカスタムフィルタが$this->paramsプロパティを活用しています。stream_filter_append()['prefix' => '...', 'suffix' => '...']のような連想配列を渡すと、フィルタ内のfilterメソッドで$this->params['prefix']$this->params['suffix']としてこれらの値を取り出し、ストリームデータに特定の接頭辞と接尾辞を追加する処理を実現しています。このように、同じフィルタクラスであっても、登録時に異なるパラメータを与えることで、柔軟なデータ変換やログ処理などを行うことができます。

$this->paramsプロパティは、stream_filter_append()stream_filter_prepend()といった関数でストリームフィルタを登録する際に、第4引数として渡された連想配列が自動的に格納される場所です。このプロパティはmixed型と定義されていますが、通常は連想配列として扱われます。パラメータが渡されない場合や、特定のキーが配列内に存在しない場合に備え、サンプルコードのように??(null合体演算子)を使ってデフォルト値を設定するなど、配列要素へのアクセスは常に堅牢に行うようにしてください。これにより、実行時エラーを防ぎ、フィルタ処理の柔軟性と安全性を高めることができます。フィルタの動作を外部から動的に制御するための重要な手段となります。

PHPカスタムフィルターでURL風パラメータを扱う

1<?php
2
3/**
4 * URLクエリ文字列のような形式のパラメータを受け取り、ストリームデータを変換するカスタムフィルター。
5 *
6 * php_user_filter::params プロパティは、ストリームフィルター登録時に stream_filter_append()
7 * や stream_filter_prepend() の第3引数で渡されるオプションのパラメータを保持します。
8 *
9 * この例では、HTTPリクエストのURLクエリパラメータに似た文字列をフィルターのパラメータとして利用する方法を示しますが、
10 * これはHTTPリクエストのURLクエリパラメータを直接処理するものではなく、
11 * ストリームフィルターのパラメータとして任意の文字列データを渡す一例です。
12 */
13class UrlLikeParamFilter extends php_user_filter
14{
15    private string $action = 'none'; // フィルターの動作を決定するアクション
16    private string $prefix = '';     // データに追加するプレフィックス
17
18    /**
19     * フィルターがインスタンス化されたときに呼び出されます。
20     * ここで php_user_filter::params プロパティから渡されたパラメータを解析し、
21     * フィルターの動作を設定します。
22     *
23     * @return bool フィルターの初期化が成功した場合は true、それ以外は false。
24     */
25    public function onCreate(): bool
26    {
27        // params は mixed 型で、stream_filter_append() の第3引数で渡された値が入ります。
28        // この例では 'action=uppercase&prefix=MY_DATA' のような文字列を期待しています。
29        if (is_string($this->params) && !empty($this->params)) {
30            // URLクエリ文字列をパースする parse_str() 関数を使用して、パラメータを連想配列に変換します。
31            parse_str($this->params, $parsedParams);
32
33            if (isset($parsedParams['action']) && is_string($parsedParams['action'])) {
34                $this->action = strtolower($parsedParams['action']);
35            }
36            if (isset($parsedParams['prefix']) && is_string($parsedParams['prefix'])) {
37                $this->prefix = $parsedParams['prefix'];
38            }
39        }
40        return true;
41    }
42
43    /**
44     * ストリームデータを処理するメインメソッドです。
45     * 入力バケットからデータを読み込み、変換し、出力バケットに書き込みます。
46     *
47     * @param resource $in 入力バケットブリッジ。ここから元のデータを受け取ります。
48     * @param resource $out 出力バケットブリッジ。ここに変換後のデータを書き込みます。
49     * @param int $consumed これまでに処理されたバイト数の合計。このメソッドで処理したバイト数を加算します。
50     * @param bool $closing ストリームが閉じられようとしているかを示すフラグ。
51     * @return int フィルターの実行結果 (PSFS_PASS_ON, PSFS_FEED_ME, PSFS_ERR_FATAL)。
52     */
53    public function filter(
54        $in,
55        $out,
56        &$consumed,
57        bool $closing
58    ): int {
59        // 入力バケットブリッジからバケットを1つずつ取り出します。
60        while ($bucket = stream_bucket_make_writeable($in)) {
61            $data = $bucket->data;
62
63            // onCreate() で設定されたパラメータに基づいてデータを変換します。
64            if ($this->action === 'uppercase') {
65                $data = strtoupper($data);
66            }
67            if (!empty($this->prefix)) {
68                $data = $this->prefix . $data;
69            }
70
71            // 変換後のデータをバケットに格納し直します。
72            $bucket->data = $data;
73            // 処理したバイト数を加算します。
74            $consumed += $bucket->datalen;
75            // 変換後のバケットを出力バケットブリッジに追加します。
76            stream_bucket_append($out, $bucket);
77        }
78
79        // 処理を続行し、次のフィルター(または最終的なストリーム)にデータを渡すことを示します。
80        return PSFS_PASS_ON;
81    }
82}
83
84// --------------------------------------------------------------------------
85// サンプルコードの実行部分
86// --------------------------------------------------------------------------
87
88// カスタムフィルターを登録します。これにより、stream_filter_append() などでフィルター名を指定できるようになります。
89stream_filter_register('url_like_param_filter', UrlLikeParamFilter::class);
90
91// 一時ファイルを作成し、ストリームとして開きます。
92// `w+` モードは読み書き両用で、ファイルが存在しない場合は作成します。
93$tempFile1 = tempnam(sys_get_temp_dir(), 'php_filter_test_1');
94if ($tempFile1 === false) {
95    die("エラー: 一時ファイルの作成に失敗しました。\n");
96}
97$fp1 = fopen($tempFile1, 'w+');
98if ($fp1 === false) {
99    die("エラー: 一時ファイル '{$tempFile1}' を開けませんでした。\n");
100}
101
102// ファイルに元のデータを書き込みます。
103fwrite($fp1, "Hello, world!\n");
104fwrite($fp1, "PHP is great.\n");
105
106// ストリームポインタをファイルの先頭に戻します。
107fseek($fp1, 0);
108
109// 読み込み操作時に適用されるフィルターをストリームに追加します。
110// 第3引数の文字列が UrlLikeParamFilter クラスの params プロパティに渡されます。
111$paramsForFilter1 = 'action=uppercase&prefix=FILTERED_';
112stream_filter_append($fp1, 'url_like_param_filter', STREAM_FILTER_READ, $paramsForFilter1);
113
114echo "--- フィルター適用後のデータ (パラメータ: 'action=uppercase&prefix=FILTERED_') ---\n";
115// フィルターを通してデータを読み込み、出力します。
116while (!feof($fp1)) {
117    echo fgets($fp1);
118}
119
120// 別のパラメータでフィルターの動作を試すために、新しい一時ファイルとストリームを作成します。
121$tempFile2 = tempnam(sys_get_temp_dir(), 'php_filter_test_2');
122if ($tempFile2 === false) {
123    die("エラー: 一時ファイルの作成に失敗しました。\n");
124}
125$fp2 = fopen($tempFile2, 'w+');
126if ($fp2 === false) {
127    die("エラー: 一時ファイル '{$tempFile2}' を開けませんでした。\n");
128}
129
130// 別のデータをファイルに書き込みます。
131fwrite($fp2, "lorem ipsum dolor.\n");
132fwrite($fp2, "The quick brown fox jumps over the lazy dog.\n");
133
134// ストリームポインタをファイルの先頭に戻します。
135fseek($fp2, 0);
136
137// 読み込み操作時に適用されるフィルターをストリームに追加します。
138// 今回はプレフィックスのみを指定し、アクションはデフォルト ('none') のままです。
139$paramsForFilter2 = 'prefix=>> ';
140stream_filter_append($fp2, 'url_like_param_filter', STREAM_FILTER_READ, $paramsForFilter2);
141
142echo "\n--- フィルター適用後のデータ (パラメータ: 'prefix=>> ') ---\n";
143// フィルターを通してデータを読み込み、出力します。
144while (!feof($fp2)) {
145    echo fgets($fp2);
146}
147
148// ストリームを閉じ、一時ファイルを削除してクリーンアップします。
149fclose($fp1);
150unlink($tempFile1);
151fclose($fp2);
152unlink($tempFile2);
153
154?>

PHPのphp_user_filter::paramsは、カスタムストリームフィルター内で利用されるプロパティです。これは、フィルターをストリームに適用する際にstream_filter_append()stream_filter_prepend()といった関数の第三引数として渡されたオプションのパラメータを保持します。このプロパティ自体に引数はなく、戻り値は渡されたパラメータの値そのものであるためmixed型となります。

サンプルコードでは、UrlLikeParamFilterというカスタムフィルターを実装し、php_user_filter::paramsプロパティにURLクエリ文字列のような形式のパラメータ文字列が渡されることを想定しています。フィルターの初期化メソッドであるonCreate()内で、このparamsプロパティから取得した文字列をparse_str()関数で解析し、フィルターの動作(例えば、データを大文字にするか、特定のプレフィックスを追加するかなど)を動的に設定しています。

この例における「php params in url」の記述は、HTTPリクエストのURLクエリパラメータを直接処理するものではなく、ストリームフィルターのパラメータとしてURLクエリ文字列形式のデータを利用していることを示しています。これにより、外部からフィルターの動作を柔軟に制御することが可能になります。実行部分では、異なるパラメータ文字列を渡すことで、同じフィルターが異なるデータ変換を行っている様子を確認できます。

php_user_filter::params プロパティは、ストリームフィルター登録時に stream_filter_append() などの第3引数で渡された値を保持します。このプロパティは mixed 型であるため、利用する際は必ず期待する型であることを確認し、必要に応じてデータ形式の解析や変換を行ってください。サンプルコードではURLクエリ文字列に似た形式でパラメータを渡していますが、これはHTTPリクエストのURLパラメータを直接扱うものではなく、ストリームフィルターへの任意のデータ受け渡しの一例としてparse_str()関数を使用しています。渡されたパラメータは外部からの入力と同様に扱い、セキュリティの観点から、信頼する前に必ず検証や無害化処理を行うことを推奨します。フィルターの初期化を行う onCreate() メソッド内で params を適切に処理し、フィルターの動作を設定することが重要です。

関連コンテンツ