今週の PHP 2022/08/06 〜 2022/08/12
PHP のメーリングリストから、気になった情報をピックアップします。
Internal
PHP: rfc:asymmetric-visibility
8.3 系に対する最初の RFC です。
object property に対する アクセス修飾子 public, private, protected で property の可視性を定めることが出来ます。
この可視性は、set get メソッドを実装した場合に同一であり、異なる可視性を指定することはできません。
この RFC は asymmetric。つまり set と get でそれぞれ異なる可視性を設定できるようにする提案です。
class Foo
{
public private(set) string $bar;
}
Constructor Promotion でも使えるようにするようです。
上の例では、get は public、set は private になります。つまり
$foo = new Foo();
echo $foo->bar; //これはOK
$foo->bar = 'fuga'; //これはNG
Readonly クラスと違って、値のセットは何回でもできます。
__set
の場合も、上記の可視性がそのまま適用されます。
今までの書き方に慣れている身としては、相当気持ち悪いプロパティ定義に見えますが、慣れの問題かな??
メモ
Swift では同様の言語仕様があるpublic private(set)
の記述があり、値の設定のみクラス内に限定させることができるとありました。
Reflection についての懸念点が上がってきています。つまり isPublic とか getModifiers とかしたときに、どう表現されるのか?ということです。
アクセス修飾子にプラスアルファの条件が追加されているので、きちんと設計しないとカオスになりそう。
C# style では駄目か?という話があった。おそらくこれのことだと思うけどpublic private(set)
に該当するようなやつを用意すればいいということかな。
この提案は、下記の3つのアクセスレベルを増やすことと同義
- "public private(set)"
- "public protected(set)"
- "protected private(set)"
※この提案では、set
のみが個別指定の対象となるpublic protected(get)
のような書き方はない。
attribute でもできるのでは? public readonly
などの書き方はどうか?
-> 見た目が自明であるし、Swift の文法に合わせたいので、元の提案通りで行きたい。
PHPStan/Psalm には @private
@internal
@phpstan-internal
があるので、今回のような仕様変更がなくても補える。
そもそも、immutable な property をできるだけ維持したいので、今回のようなケースはレア。値を更新したかったら、Readonly のオブエジェクトをつく直せ。という意見も
それに対して、PHPStan/Psalm でサポートするなら、言語側で対応して、みんなに使ってもらおうよ!という意見。たしかに。
コメントが沢山ついていて、読むのも大変です。
Larry さんは、さらなるユースケースなどについて、コメントしたいということで、フォローアップを待っていてねということです。
RFC Idea - is_json - looking for feedback
今週もアイデア募集中です。
コメントが来ています。
- filter_var はいいかもしれないけど、
is_json
のがグッとくるよね -
is_json_valid
の方が、認識の齟齬がないと思う
実装上の懸念としては、RFC の理由の一つとなっているメモリ使用量について。
- 実際に文字列を parse せずに、正しい JSON であるかどうかを判断できるのか?
- PCRE(正規表現) でやるんだろうけど、正確な実装ができるのか疑問
来週にも RFC を用意するということです。Karma Request が来たので、RFC の準備を始められたようです。
RFC Idea: Introducing a ReflectionWithAttributes interface - Looking for feedback
ReflectionWithAttribute Interface の提案です。
PHP に Attribute に追加されたのは、8.0 からです。
Reflection 関連で、Attribute をうまく扱うインタフェースを追加したいということのようです。
あったほうが良さそうですね。無理やりパースして取得みたいな羽目になるのはつらそうです。
[Concept] Extension methods
既存のクラスに対して、特定の機能を持つ関数を追加するような仕組みの導入提案です。
例としては Collection
のようなクラスに map
メソッドを追加しています。
(new Collection(1,2,3))
->map(fn ($value) => $value +1)
->map(fn ($value) => $value +2);
map は Collection を返す関数として定義することで、次々に関数を適用していくようなコードをスッキリ書けます。
かつ、IDE に map を補完させることもできます。
同様の機能性を提供しようとした RFC として Pipe Operator が紹介されています。
却下された提案ですが、やりたいことは stream に対する filter みたいな操作をきれいに書きたいという感じでしょうか。
これって、ruby だと mixin になるんでしょうか?英語では、Monkey Patching と呼ぶようです。
既存クラスへの機能追加が出来ると、継承を使わずに、かつ元のコードに影響を与えずに機能性を充実させることが可能です。
この提案に対するコメントとして
- 名前空間の衝突
- コンパイル時に不正なextensionの利用を検知できるのか?
既存クラスを変更せずに機能性を追加する方法としては、デコレーターパターンなどもありますが、今回の提案は、クラスをこじ開けて機能を追加するという感じで、とても強力な言語機能に見えます。
刺激的なアイデアですので、コメントもたくさんついています。今後の展開が注目されます
Bugs
Function to validate regular expression · Issue #9289 · php/php-src
正規表現のバリデーションを行う関数が無いんじゃない?というイシュー
preg_validate
とかどうよ?とか、filter_var
だろ?とかの話がされています。
Featureリクエストなので、RFC が出される流れになるかと思います。
正規表現には各種方言がありまして、私の知る限り現状の PHP には
- PCRE (preg系)
- Oniguruma (mb_ereg系)
の2系統があります。Oniguruma は https://github.com/kkos/oniguruma/blob/master/doc/RE.ja を見る限りは PCRE のパターンも入っているようです。
イシューには、mb_string の話は一切でてきてないので、十中八九は preg 系の正規表現のみが対象になることでしょう。
php bug ? addition · Issue #9286 · php/php-src
<?php
php -r 'ini_set("precision", 20); var_dump(17.52+69.05+13.43);'
php -r 'ini_set("precision", 20); var_dump(69.05+13.43+17.52);'
上記、計算結果が float(100)
に両方ともならないのはおかしいというイシューでした。
=> float(100)
=> float(99.999999999999)
不動小数点計算に関するイシューです。例によって IEEE 754 をご案内して終了
GC root buffer keeps growing when destructors are present · Issue #9266 · php/php-src
destructor
が記述されたクラスが含まれた際に、GC でメモリリークが発生しているというイシュー。
参照カウントがおかしかったようで、下記の修正コミットを見てもわかるようにカウントの計算に微修正が入っています。
SIGPIPE while using curl · Issue #8309 · php/php-src
cURL が SIGPIPE を出すというイシュー。クローズされています。
AMD64(Debian Buster) で OpenSSL 1.1.1n ということで、もしかしたら同様事象に出会っている人はいそう。
問題はPHPではないということでクローズされてますので、同様事象の方はライブラリ(cURLのcライブラリ, Guzzle)か、OSのアップデートを検討すると良さそう。
Segmentation fault in mb_strimwidth() · Issue #9248 · php/php-src
最新の master で mb_strimwidth
が segv を起こしていたというもの。
変数の初期化ミスだったようですが、mb_string って結構アクティブに手が入っているねという印象を受けました。
PHP 8.2 readonly classes allow inheriting mutable properties from traits · Issue #9285 · php/php-src
Readonly クラスが trait 経由で Mutable なプロパティーを継承できてしまうというイシュー
あまり良い解決策じゃないけど...という注釈付きでコミットされた修正が下記。
インタフェースと同様に、Readonlyクラスでtrait を使うとエラーになります。修正は未来に任せたという雰囲気がします。
ksort(..., SORT_REGULAR)
behaves incorrectly on arrays with string and numeric keys since PHP 8.0 · Issue #9296 · php/php-src
8.0 以降で ksort の振る舞いが正しくないというイシュー
これは、8.0 以降で、文字列と数値の比較に変更が入ったにも関わらず、ksort が古いルールに従っているのが原因とのこと
ksort のマニュアルはこちら。key で比較して並べ替えを行います。
8.0 以降の正しい挙動は、600が先にくるべきです。
array(2) {
[600]=>
int(0)
["aaa"]=>
int(1)
}
int(-1)
つまり、問題の根幹はこっち
修正はこのコミット
pecl.php.net site is down · Issue #9307 · php/php-src
pecl のサーバーが数時間にわたって落ちてました。
コンテナビルドで pecl install xxx
とやっている場合に、ライブラリのソースコードがダウンロードできず、コンテナのビルドが止まるなどのツイートが多く見られました。
基本的には、Github で管理されているライブラリーが多いので、 Github 側のアーカイブをダウンロードして
phpize
./configure
make
make install
すれば、急場はしのげます。
is_numeric() limitation · Issue #9311 · php/php-src
is_numeric
が Exponent 表現も true を返すのだが、チェック出来ないだろうか?というイシュー
is_numeric
は文字列が数字表現であることをチェックする関数なので、質問者が要求する INT か FLOAT かというチェックには向いていません。
FILTER_VALIDATE_FLOAT
FILTER_VALIDATE_INT
を使って、 filter_var
でチェックするのが適切だろうということで回答がついています。
Fatal error: class and trait define the same constant in the composition of child class in case constant in trait is equal to constant in child class · Issue #9272 · php/php-src
継承関係にあるクラスが同じコンスタント名を使って、かつ Trait 側でそのコンスタントを参照するとエラーになるというもの。
sji さんからのコメント
- コンパイル時に未定義のクラスの定数を参照しようとしているので、エラーになるべきということ
- self に置き換えると実行可能になるのは、ランタイムで参照されるようになるからということ
パット見は、頭が混乱してしまうコードですね。
Discussion