😺

今週の PHP 2022/12/03 〜 2022/12/09

2022/12/29に公開

PHP のメーリングリストから、気になった情報をピックアップします。

Internal

PHP Core Roundup #8 — The PHP Foundation

https://thephp.foundation/blog/2022/11/30/php-core-roundup-8/

PHP Foundation から Roundup #8 の報告が上がってきています。

目についたトピック

最後の Impact and Transparency Report は PHP Foundation がどれくらいPHPに寄与したのかが書かれたリポートです。

内容をかんたんにまとめると

  • PHP Foundation は ボランティア管理人10名、パートタイムの開発者6名
  • 1400名の個人 & 団体から58万ドルの寄付が集まった
  • 6名の開発陣は2022年4月から雇用されていて、PHPの半分のコミットとレビューを担当
  • 2023年は約68万ドルの予算で開発陣を拡充していく予定
  • 目標
    • 開発チームの拡充
    • 管理グループ、開発チームを含む開発プロセスの確立
    • スポンサーとのコミュニケーションの充実、関係性の決定
    • パートナーシップなどの模索
    • RFCや、追加開発アイデアの品質向上
    • PHP Foundation によるハイレベルなロードマップの構築

という感じで、PHP Foundation からは定期的にお便りが届きますので、我々としてはこれからも寄付やOSSで貢献していきたいですね。

Please allow an out of readonly properties - Externals

https://externals.io/message/119079

Readonly properties を Reflection を使って編集できるようにしてくれませんかというお便り。

すこし厳しいトーンの拒絶の意見が続きましたが、Andreas さんがきれいにまとめてくれていました。

もし、利用している Library や API が Readonly Properties を使っているのなら、その理由があるはずで、その Property を自分たちが変えたいと思っているということは、そもそも自分たちの要求が Library に合ってないわけなので、要求から見直すほうが良いかもしれませんね。といった感じのコメントでした。

インターナルでのコメントは、落ち着いた意見が多いのですが、今回は少しエキサイトした感じの意見交換もあったので、冷静にやっていきたいものだと思いました。

PHP 8.2.0 Released! - Externals

https://externals.io/message/119096

Release ページの新規フィーチャー紹介サンプルコードがイカしてない!ということで、何個か指摘が入っています。

  • DNF Type 使っているのに null チェックしている
  • Trait の Constant は宣言時に Fatal エラーがでるので、コメントがおかしい

などなど、こういう細かいサンプルの間違えで、入門者の人が混乱したりもするので、良いことだなと思います。

[RFC][Dynamic class constant fetch] - Externals

https://externals.io/message/118960

まてまて、まだまだ議論が足りんぞ、このまま Vote に行っちゃいかん!というわけで、コメントが入ってました。
 
提案されている内容に対して、既存の言語機能でも対応できるのでは?といった話や、constant の動的検証で失敗した場合に、null 合体演算子でデフォルトを使えるようにするのは?みたいな話が追加で話されています。

[RFC][List/Assoc\unique] - Externals

https://externals.io/message/119070

array_unique が一部対応してないキー項目があるということで、ARRAY_UNIQUE_IDENTICAL フラグを追加しようという動きがありましたが、コミュニティの大勢がそれは新しい関数にすべきだろうというスタンスを取っていたので、新しい関数として RFC が提出されました。

https://wiki.php.net/rfc/list_assoc_unique

提出されたはいいけど、まだ議論は少なめです。個人的にはフラグでもいいかなと思っていた案件でした。

Bugs

WeakMap prevents garbage collection · Issue #10043 · php/php-src

https://github.com/php/php-src/issues/10043

class Canary extends stdClass
{
    public function __construct(public string $name)
    {
    }

    function __destruct()
    {
        echo $this->name."\n";
    }
}

$container = new Canary('container');
$canary = new Canary('canary');
$container->canary = $canary;

$map = new \WeakMap();
$map[$canary] = $container;

echo 1;
unset($container, $canary);
gc_collect_cycles();
echo 2;

オブジェクトを WeakMap に詰めると、gc_collect_cycles() で GC されないというイシュー。

コメントを見ると、gc で重要となる参照カウントの仕様だからしょうがないという反応なのだけど、そもそも WeakMap を知らなかった。

https://www.php.net/manual/ja/class.weakmap.php

WeakMap は、 オブジェクトをキーとして受け入れるマップ(辞書)です。 SplObjectStorage と似ていますが、 WeakMap のキーとなるオブジェクトは、 オブジェクトのリファレンスカウントが更新されません。 つまり、WeakMap のキーとなっているオブジェクトだけが唯一の残された参照だった場合、 オブジェクトはガベージコレクションの対象となり WeakMap から削除されます。 WeakMap の用途は、 長く生き残る必要がないオブジェクトから派生した、 データのキャッシュを作ることです。

この説明を読む限り、上のコード例に異を唱える気持ちが一気にわかるようになります。

unset($container, $canary) によって、唯一の参照が消えたのだから、gc_collect_cycles で GC されるべきだろう?と

つまり、想定されるアウトプットは GC による __destruct を挟んで、下のようになるはず。

1container
canary
2

中の人からの返信は、問題となっているのは Weekmap の値側にインスタンスを指定していることで、キー側だけの問題であれば GC されるよ?ということ

https://3v4l.org/Ic0YC

なるほど、分かりやすい。

the "weak"-ness of WeakMap applies to the keys but not the values.

というコメントもありました。少なくとも、内部実装としては key にのみ Weak という表現が当てはまるようです。
勉強になりますね。

ここから、話は進んで、この挙動を是とするかいなかという話に発展しています。JS では同様ケースでも GC されるよという意見もでており、新しい RFC の予感です。

Fix bug #79836: Segfault in concat_function by nielsdos · Pull Request #10049 · php/php-src

https://github.com/php/php-src/pull/10049

concat (文字列結合) で SegV が出るという現象に対する PR です。
修正はされてるけど、メモリーリークがあるということで、まだ修正が続いています。

Use fast text conversion filters to implement mb_convert_variables by alexdowad · Pull Request #9966 · php/php-src

https://github.com/php/php-src/pull/9966

配列や変数に格納された文字の文字コード変換を一気に行う関数 mb_convert_variables の速度改善PR
例によって、Major Overhaul と呼ばれる活動の一つです。

修正内容を見ると、独自実装の部分を、関数 php_mb_convert_encoding_ex に移譲するように修正されているので、良さそうな気がします。

Simplify decoding filter for UTF-8 by alexdowad · Pull Request #10013 · php/php-src

https://github.com/php/php-src/pull/10013

UTF-8 のデコードフィルターを単純化するという PR
こちらも、 Major Overhaul 活動の一環と思われます。精力的だなぁ。

Implement short functions with auto capture by arnaud-lb · Pull Request #8330 · php/php-src

https://github.com/php/php-src/pull/8330

すでに却下された RFC の PoC ですが、short functions ファンからのアツイお便りが届いていました。

RFC のときのやりとりはこちら https://externals.io/message/117888

根強いファンもいるし、もう少しで受理されそうな RFC なので、ぜひ Take3 にチャレンジして欲しいです。

standard/basic_functions.c remove x bit on this file by devnexen · Pull Request #10069 · php/php-src

https://github.com/php/php-src/pull/10069

えらい!という PR
x bit いらんよね!

[grammar] "less security-conscience applications · Issue #10056 · php/php-src

https://github.com/php/php-src/issues/10056

英語のお勉強

security conscience -> security-conscious

Browscap crashes PHP 8.1.12 on request shutdown (apache2) · Issue #10052 · php/php-src

https://github.com/php/php-src/issues/10052

そもそも browscap を知らなかった。

https://browscap.org/

どうやら、UA と実行環境の紐付一覧のようなもので、これを ini で設定しておくと、get_browser でいい感じに取れるらしい。知らなかった...

ともあれ、これが PHP 8.1.12 の Request Shutdown でクラッシュするというイシュー

Segfault in opcache during autoloading of class in destructor · Issue #9853 · php/php-src

https://github.com/php/php-src/issues/9853

destructor から autoloading すると OPCache が SegV を出していたというイシュー。
結局は、報告主の vendor ディレクトリがおかしくなっていたのが原因らしく、 composer update したら再現しなくなってしまったとのこと。

とはいえ、コミッターの方々は気になりそうな案件

If "php-fpm --nodaemonize" is called to be sent into background it forces itself into FG and hangs the calling process · Issue #10058 · php/php-src

https://github.com/php/php-src/issues/10058

プロセスとしての php-fpm の挙動についてのイシュー。この辺は、オーケストレーションツール関連でも一度出てきました。
明文化されていないことが問題というよりは、実行プラットフォームによっても挙動が異なってしまうようで、頭の痛そうな問題。

max_allowed_packet=16777216 causes test failure on ext/mysqli/tests/mysqli_real_connect_compression_error.phpt · Issue #10063 · php/php-src

https://github.com/php/php-src/issues/10063

mysql のプロトコルに起因するテスト失敗のイシュー。

これに起因して、MariaDB を test DB に含めようというイシューも上がっています。MySQL 5.7 も影響と書いてあるのでちょっと気になる。

https://github.com/php/php-src/pull/10062

よく、原因不明として扱われる MySQL server has gone away が出てきているので、もう少し詳しく見ておきたいイシュー。

var_export on anonymous classes · Issue #10066 · php/php-src

https://github.com/php/php-src/issues/10066

var_export のマニュアル説明では

https://www.php.net/manual/ja/function.var-export.php

var_export() は、 渡された変数に関する構造化された情報を返します。この関数は var_dump() に似ていますが、 返される表現が有効な PHP コードであるところが異なります。

となっているにも関わらず、temoporary な情報が含まれたコードが出力されるというイシュー。

https://3v4l.org/CQ6qK

本当は new class{} となるのが正しいような気がします。いずれにしろ復元のことを考えて、__set_state メソッドを実装する必要はありそうですが。

無名クラスは、テストなどでもよく活用するので、このような既存挙動の変なところは覚えておくと、いつか役に立ちそう。(その前に修正されそうだけど)

Rename PHP_STREAM_TO_ZVAL to PHP_STREAM_FROM_ZVAL by nielsdos · Pull Request #10065 · php/php-src

https://github.com/php/php-src/pull/10065

マクロの名前が実態と逆になっているという internal での指摘がそのまま PR になってマージされました。素晴らしい。

PHP 8.2.0 access violation while executing a 'foreach' loop · Issue #10067 · php/php-src

https://github.com/php/php-src/issues/10067

Windows で foreach 回すとなんの手がかりもなく落ちるというイシュー
ZTSの問題のようですが、回避策としては access by referrence にすると、とりあえずクラッシュは避けられるようです。

開発時に問題になるやつですね。(多分、本番は Linux 環境が多いので)

PHP crashes when execute_ex is overridden and a __call trampoline is used from internal code · Issue #10072 · php/php-src

https://github.com/php/php-src/issues/10072

trampoline ってなんですかというレベルです。

https://gcc.gnu.org/onlinedocs/gccint/Trampolines.html

これかなぁ....

[Stream] STREAM_NOTIFY_PROGRESS over HTTP emitted irregularly for last chunk of data · Issue #10031 · php/php-src

https://github.com/php/php-src/issues/10031

Windows で WSL 使っていると発生するようです。データ同期周りのレースコンディションなのかなという気持ち。

Static in combination with anonymous class does not behave as expected · Issue #2047 · php/doc-en

https://github.com/php/doc-en/issues/2047#issuecomment-1342613243

無名クラス内での static の利用について、ドキュメントに明記されていないが、想定どおりに動かないという報告

こちらは、RFC には一応記載があるようなので、ドキュメントイシューになりました。

https://wiki.php.net/rfc/anonymous_classes#internal_class_naming

Multiple anonymous classes created in the same position (say, a loop) can be compared with ==, but those created elsewhere will not match as they will have a different name.

Discussion