📘

今週の PHP 2022/11/05 〜 2022/11/11

2022/11/15に公開

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

PHP 8.2 は 12/8 にリリース日がリスケされました。OPCache 周りの不具合修正が必要なためです。もう少し我慢しようね!!

Internal

[RFC][Discussion] Objects can be declared falsifiable

改ざん可能なオブジェクトの宣言についてという議論。以前提出した RFC に再挑戦しようということです。

RFC の意図がわからないとなんともいえないので、まずは RFC を読んでみましょう。

https://wiki.php.net/rfc/objects-can-be-falsifiable

要約

新しいインタフェース Falsifiable と、マジックメソッドの __toBool() を追加しようというもの。

通常はインスタンスに対しては、true という判断しかできませんが、オブジェクト自身が true/false を表現できるようにしよう。

interface Falsifiable
{
  public function __toBool(): bool;
}

このインタフェースを継承している場合に限って、インスタンスは Falsifiable つまり False になりうる。

議論

つまり、現状のインターナルでの議論は、オブジェクトの改ざんについてなので、改ざんされたオブジェクトが __toBool で false を返せれば、改ざんが検知できるということらしい。
PHP のスカラー型は、それぞれ false と判定される状態をもっているので、オブジェクトだってもってもいいじゃんという感じ。

SimpleXMLElement インスタンスで、属性が空だと false って判定されるぞ!というご意見
いや、このアイデアはいかんぞ!というご意見
if($obj) の意味が変わってしまう。(ごもっとも)

いやいや、null と false は違うやろ!

などなど、たくさんの議論が出ていて面白いです。

if($obj) については、if(is_null($obj)) などの型に対して正確な条件を考えると、むしろ falsifiable というのが正しい概念なのではという気がしてきます。

ともあれ、今後が楽しみな RFC です。

PHP: rfc:dynamic_class_constant_fetch

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

現状、定数を動的に読み出すには、constant 関数を使って、こんな書き方をする。

https://3v4l.org/NrfSF

この RFC は、もうちょっと直感的に、楽に、動的に定数参照することを可能にする機能追加に対する RFC です。

echo Foo::{$bar}; 

インターナルでは、こんな議論がされています。

  • constant() で出来るじゃん?キーストロークが減るだけ?
  • いやいや、全体的な動的参照と一貫性が出るので、素晴らしい変更だ!
  • constant() を非推奨にするのもプランにいれてくれ

PoC はこちら

https://github.com/php/php-src/pull/9793/files

この RFC が通ると、Backed Enum の値の参照が、変数定義時、コンスト定義時に使えるようになるので、個人的にめちゃくちゃ入って欲しい。

[RFC][Discussion] Arbitrary static variable initializers - Externals

https://externals.io/message/118976

static に任意の式を代入できるようにするという RFC

すでに PoC もでています
https://github.com/php/php-src/pull/9301

現状エラーになってしまうこういう表現が出来るようになります。

https://3v4l.org/gTufh

RFC [Discussion]: Randomizer Additions - Externals

https://externals.io/message/118810

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

下記の2つについて、Vote が開始されました。

Randomizer::getBytesFromString()

Randomizer::nextFloat(), Randomizer::getFloat(), and the IntervalBoundary enum

現状は、圧倒的多数で可決される見込みです。

PHP: rfc:destructuring_coalesce

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

Vote が開始されました。配列を変数に分解してアサインするときに、null 合体演算子で初期値を定義できるようにするものです。
BCブレークもないし、比較的穏便な RFC なので、受けいられるかなと思っていたのですが、現状は厳しそうです。

普通に入ると思ってたのですが、シンタックスが分かりにくいという意見があったりと、逆風です。
ちょっと RFC 作成段階でのコミュニケーションが少なかったかなぁという印象。

PHP: rfc:asymmetric-visibility

https://wiki.php.net/rfc/asymmetric-visibility

Read と Write で可視性を変更できるようにしようという RFC ですが、今週少し動きがありました。

class Foo
{
    public private(set) string $bar;
}

PoC の実装を進めているようですが、デザイン的な問題にぶつかったとのことで、インターナルに相談がきています。

現在決まっているデザイン決定は2つ

  1. 指定されている場合、set の可視性は、get の可視性よりも狭まっていなければならない。 protected protected(set) protected public(set) はNG
  2. readonly は、一度だけ書き込みができるフラグとして、非対象可視性に組み合わせられる。もし、 set の可視性が指定されていない場合、readonlyprivate(set) を意味する。

問題になるのは、readonly との組み合わせの部分

public public(set) readonly string $foo
protected protected(set) readlonly string $foo

継承を使って、子クラスでメンバ変数に値を設定しようとすると、 private(set) として認識されると、使えなくなってしまう。
というわけで、3つの提案が来ている。

  1. readonly の場合は protected protected(set) を認める
  2. readonly と非対称性可視性は混ぜるな危険にする
  3. もっと素晴らしいアイデア

なお、実装者としては、1は実装的には楽らしい。ただし、分かりにくいし説明が難しい。
PHP としては、explicit over implicit な傾向があると思うので、隠れた仕様みたいなものは嫌われそう。

これに対して、そもそも非対称の可視性は複雑すぎるだろう??メリットよりもデメリットのほうが多くないか?などの議論がされています。
やはり、readonly が現れると、継承周りに無理が生じてくるんだなと、感じます。

提案されたときは、まあ入っても良いかもと思いましたが、readonly との棲み分けがスッキリしてくれないと、PHP を利用するユーザーは困惑してしまうかもしれません。

Bugs

Make class_alias() work with internal classes · Issue #9826 · php/php-src

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

そもそも、PHP に internal class ってあるのだろうか?
クラス内にクラスを書くことじゃないとするなら、いったいここでいう internal class というのは、何を指しているのだろうか...

分からない

https://3v4l.org/m2clO#v8.1.12

つまり、拡張などで定義されたクラスのことを internal class と読んでいました。 @do_aki さんありがとう!

constant() behaves inconsistent when class is undefined · Issue #9905 · php/php-src

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

class が存在してないとき、constant 関数が Fatal Error を出してしまうという件。
要するに、例外としてアプリケーション側で抑え込むことができないよということ。

https://github.com/php/php-src/commit/4b1feda574a9b4c178e4e2de5ffa22b6927e9d4d

修正が入ったので、こちらはじきにリリースされるでしょう。

Add argument $callingScope to magic methods get/set/isset/unset · Issue #9906 · php/php-src

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

Magic Method に callingScope を追加しよう!という機能提案イシュー

callingScope にはクラス名が入るということで、継承関係がある際に、親クラスだったら、子クラスだったらというロジックが書きやすくなるという提案です。

私などは、こういう提案を受けたら、むしろ親と子で、無理に共通化する必要はなくて、それぞれで分けて書いたほうが安全ではと思ってしまう。
parent の参照が出来るので、子クラス側のロジックは安定するはず。

現状でも Reflection を使えば取れます。
イシューに記述されていたロジック例から転載

class Foo extends Bar
{
	public function __get($name): mixed
	{
		$frame = debug_backtrace(\DEBUG_BACKTRACE_PROVIDE_OBJECT | \DEBUG_BACKTRACE_IGNORE_ARGS, 2)[1];

		$callingScope = $frame['class'] ?? null;

		if (\ReflectionProperty::class === $callingScope) {
			$callingScope = $frame['object']->class;
		}

		// Now we can implement visibility-related logic for accessing $name

		// Let's say we want to call parent::__get() and it uses the same logic to extract the calling
		// scope, it's now broken because instead of getting frame `[1]`, it should use frame `[2]`,
		// but knowing this requires more non trivial logic. 
	}
}

realpath and readfile (and probably others in zend_virtual_cwd) fail with valid path of length 4095 · Issue #9903 · php/php-src

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

realpath 関数に 4095 バイトの文字列を与えると、false が帰ってきてしまうという不具合。
パスとして正しい文字列でも false が返ってくるということで、バグとして扱われています。

Entering shutdown sequence with a fiber suspended in a Generator emits an unavoidable fatal error or crashes · Issue #9916 · php/php-src

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

Fiber 系の不具合です。Fiber と Generator を組み合わせたコードで、Fatal Error と クラッシュの報告。
別に混ぜるな危険な技術同士ではないので、行けそうな気もしたのですが、駄目なようです。

両方とも、実行状態を停止して保持する機能なので、面倒くさそうな不具合です。

Partially support first-class callable syntax in constant expressions · Issue #9236 · php/php-src

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

第一級コーラブルを constant で使わせてくれというイシュー。

https://github.com/php/php-src/pull/9301 この PR で出来るようになるよというコメントがあったけど、static と constant は違うよなぁと思いつつ。

もしかしたら、 https://wiki.php.net/rfc/dynamic_class_constant_fetch こっちの RFC のことだろうか。

ともかく、Constant で式を書かせてくれ、Constant に実行時に定まる値を入れさせてくれという要望が多いですね。

License information for xxHash is not included in README.REDIST.BINS file · Issue #9918 · php/php-src

https://github.com/php/php-src/issues/9918#event-7782408870

xxHash のライセンス情報が入ってませんよ?というイシュー

https://github.com/php/php-src/pull/9919/files

ライセンス情報がマージされて解決。
こういうの大切。

Error: Access to undeclared static property Kint\Kint::$depth_limit · Issue #9928 · php/php-src

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

俺たちは Kint じゃないぞ?ということで即クローズ

Discussion