今週の PHP 2022/11/05 〜 2022/11/11
PHP のメーリングリストから、気になった情報をピックアップします。
PHP 8.2 は 12/8 にリリース日がリスケされました。OPCache 周りの不具合修正が必要なためです。もう少し我慢しようね!!
Internal
[RFC][Discussion] Objects can be declared falsifiable
改ざん可能なオブジェクトの宣言についてという議論。以前提出した RFC に再挑戦しようということです。
RFC の意図がわからないとなんともいえないので、まずは RFC を読んでみましょう。
要約
新しいインタフェース 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
現状、定数を動的に読み出すには、constant
関数を使って、こんな書き方をする。
この RFC は、もうちょっと直感的に、楽に、動的に定数参照することを可能にする機能追加に対する RFC です。
echo Foo::{$bar};
インターナルでは、こんな議論がされています。
-
constant()
で出来るじゃん?キーストロークが減るだけ? - いやいや、全体的な動的参照と一貫性が出るので、素晴らしい変更だ!
-
constant()
を非推奨にするのもプランにいれてくれ
PoC はこちら
この RFC が通ると、Backed Enum の値の参照が、変数定義時、コンスト定義時に使えるようになるので、個人的にめちゃくちゃ入って欲しい。
[RFC][Discussion] Arbitrary static variable initializers - Externals
static に任意の式を代入できるようにするという RFC
すでに PoC もでています
現状エラーになってしまうこういう表現が出来るようになります。
RFC [Discussion]: Randomizer Additions - Externals
下記の2つについて、Vote が開始されました。
Randomizer::getBytesFromString()
Randomizer::nextFloat(), Randomizer::getFloat(), and the IntervalBoundary enum
現状は、圧倒的多数で可決される見込みです。
PHP: rfc:destructuring_coalesce
Vote が開始されました。配列を変数に分解してアサインするときに、null 合体演算子で初期値を定義できるようにするものです。
BCブレークもないし、比較的穏便な RFC なので、受けいられるかなと思っていたのですが、現状は厳しそうです。
普通に入ると思ってたのですが、シンタックスが分かりにくいという意見があったりと、逆風です。
ちょっと RFC 作成段階でのコミュニケーションが少なかったかなぁという印象。
PHP: rfc:asymmetric-visibility
Read と Write で可視性を変更できるようにしようという RFC ですが、今週少し動きがありました。
class Foo
{
public private(set) string $bar;
}
PoC の実装を進めているようですが、デザイン的な問題にぶつかったとのことで、インターナルに相談がきています。
現在決まっているデザイン決定は2つ
- 指定されている場合、set の可視性は、get の可視性よりも狭まっていなければならない。
protected protected(set)
protected public(set)
はNG -
readonly
は、一度だけ書き込みができるフラグとして、非対象可視性に組み合わせられる。もし、 set の可視性が指定されていない場合、readonly
はprivate(set)
を意味する。
問題になるのは、readonly
との組み合わせの部分
public public(set) readonly string $foo
protected protected(set) readlonly string $foo
継承を使って、子クラスでメンバ変数に値を設定しようとすると、 private(set)
として認識されると、使えなくなってしまう。
というわけで、3つの提案が来ている。
-
readonly
の場合はprotected protected(set)
を認める -
readonly
と非対称性可視性は混ぜるな危険にする - もっと素晴らしいアイデア
なお、実装者としては、1は実装的には楽らしい。ただし、分かりにくいし説明が難しい。
PHP としては、explicit over implicit な傾向があると思うので、隠れた仕様みたいなものは嫌われそう。
これに対して、そもそも非対称の可視性は複雑すぎるだろう??メリットよりもデメリットのほうが多くないか?などの議論がされています。
やはり、readonly が現れると、継承周りに無理が生じてくるんだなと、感じます。
提案されたときは、まあ入っても良いかもと思いましたが、readonly との棲み分けがスッキリしてくれないと、PHP を利用するユーザーは困惑してしまうかもしれません。
Bugs
Make class_alias() work with internal classes · Issue #9826 · php/php-src
そもそも、PHP に internal class ってあるのだろうか?
クラス内にクラスを書くことじゃないとするなら、いったいここでいう internal class というのは、何を指しているのだろうか...
分からない
つまり、拡張などで定義されたクラスのことを internal class と読んでいました。 @do_aki さんありがとう!
constant() behaves inconsistent when class is undefined · Issue #9905 · php/php-src
class が存在してないとき、constant
関数が Fatal Error を出してしまうという件。
要するに、例外としてアプリケーション側で抑え込むことができないよということ。
修正が入ったので、こちらはじきにリリースされるでしょう。
Add argument $callingScope to magic methods get/set/isset/unset · Issue #9906 · php/php-src
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
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
Fiber 系の不具合です。Fiber と Generator を組み合わせたコードで、Fatal Error と クラッシュの報告。
別に混ぜるな危険な技術同士ではないので、行けそうな気もしたのですが、駄目なようです。
両方とも、実行状態を停止して保持する機能なので、面倒くさそうな不具合です。
Partially support first-class callable syntax in constant expressions · Issue #9236 · php/php-src
第一級コーラブルを 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
xxHash のライセンス情報が入ってませんよ?というイシュー
ライセンス情報がマージされて解決。
こういうの大切。
Error: Access to undeclared static property Kint\Kint::$depth_limit · Issue #9928 · php/php-src
俺たちは Kint じゃないぞ?ということで即クローズ
Discussion