PHPで 'resource' は引数などの型にできない・・・どうしろと

2023/03/23に公開
2

結論

PHP8でfopenなどの型であるresourceを関数の引数として宣言したらエラーを吐いた。
どうやら'resource'は型宣言出来ないらしい。
本来どうするべきなのか。。。
ご存じの方居ましたら、コメントをお願いします。

(2023/03/24:追記)
sjiさんのコメントの通り、[SplFileObject]を使うことで引数として型宣言出来ました!

https://zenn.dev/link/comments/a9a7f5ebc3ec2b
修正内容は下記となります。
https://github.com/ryotashona/benchmark/commit/c0dd385965e0fbc51eb3b822851a79358ed500f9
読み出しでforechを使っていますが、[fgetcsv]を使うことで既存によせた実装も可能です。
詳しくは下記の例を参照してください。
https://www.php.net/manual/ja/splfileobject.fgetcsv.php

改めてsjiさんに感謝を。

背景

今まではPHP5からのアップデートなどばかりで、型宣言を省略していた。
なので、勉強のために書くコードぐらいキチンと型宣言するかと思ったら、エラーになった。。。どうしろと。。。

48行目あたりの↓です。

function outputCsv($fp_out, array $row) {

本来どうすべきか分かる方居ましたら、ぜひコメントをお願いします。
https://github.com/ryotashona/benchmark/blob/dev/src/back/php/php/io.php
参考情報:PHPとrustとgolangの適当ベンチ作っててぶち当たりました。

まとめ

PHPはこれからどうなっていくんだろう。。。
『あなたは型宣言してもいいし、しなくてもいい。ただし、一部は型として使えない』『あなたはスコープを気にせずに変数宣言できる。ただし、未宣言の変数は使えない』
ますます、コードが荒れるのでは?

Discussion

sjisji

resource は実質的に公開メソッドやプロパティを持たない非透過のオブジェクトです。PHP で OOP 機能が強化される前から存在したもので、ソケットだろうが stream だろうが GD の画像ハンドルだろうがとにかく全部 区別なく resource、という、C なんかでいう void ポインタばりに型情報のない存在です。型が値に対して可能な操作を規定できていない。

それで「この値は resource です」という指定がほとんど何の情報も持たないので、型宣言としても特に指定できないようになっています。

一方で、近年ソケットなどの元々 resource だったものが徐々に固有のクラスを持つ本物のオブジェクトへ移行してきており、resource そのものはだんだんと PHP 自体から姿を消していく流れになっています。
https://github.com/php/php-tasks/issues/6

というわけで、将来的には resource 自体は死滅するんじゃないでしょうか。

中身がファイルハンドルな resource を扱いたい時はクラスでラップするなどして、扱う側で型情報が意味を持つようにすると比較的安全です。または可能な場合は、最初から SplFileObject あたりで取り回すほうが楽かもしれません。

ryotashonaryotashona

sjiさん
コメントありがとうございます。
【C なんかでいう void ポインタばりに型情報のない存在です。】わかりやすかったです。
確かにそのようなものであれば、こういう扱いになるのも納得です。
SplFileObject知りませんでいた、使ってみます。
リンク先も後で詳しく流れを追ってみます。
ありがとうございました。