Π‘ΠΈΠ½ΡΠ°ΠΊΡΠΈΡ ΡΠΎΠ·Π΄Π°Π½ΠΈΡ ΠΏΠ΅ΡΠ²ΠΎΠΊΠ»Π°ΡΡΠ½ΡΡ
callable-Π·Π½Π°ΡΠ΅Π½ΠΈΠΉ
Π‘ΠΈΠ½ΡΠ°ΠΊΡΠΈΡ ΠΏΡΠ΅ΠΎΠ±ΡΠ°Π·ΠΎΠ²Π°Π½ΠΈΡ callable-Π²ΡΡΠ°ΠΆΠ΅Π½ΠΈΠΉ Π² ΠΎΠ±ΡΠ΅ΠΊΡΡ ΠΏΠ΅ΡΠ²ΠΎΠ³ΠΎ ΠΊΠ»Π°ΡΡΠ°, ΠΊΠΎΡΠΎΡΡΠ΅ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ
ΠΏΠ΅ΡΠ΅Π΄Π°Π²Π°ΡΡ ΠΊΠ°ΠΊ Π°ΡΠ³ΡΠΌΠ΅Π½Ρ, Π²ΠΎΠ·Π²ΡΠ°ΡΠ°ΡΡ ΠΈΠ· ΡΡΠ½ΠΊΡΠΈΠΉ ΠΈΠ»ΠΈ ΠΏΡΠΈΡΠ²Π°ΠΈΠ²Π°ΡΡ ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΠΌ,
ΠΏΡΠ΅Π΄ΡΡΠ°Π²ΠΈΠ»ΠΈ Π² PHP 8.1.0 ΠΊΠ°ΠΊ ΡΠΏΠΎΡΠΎΠ±, ΠΊΠΎΡΠΎΡΡΠΉ
ΡΠΎΠ·Π΄Π°ΡΡ Π°Π½ΠΎΠ½ΠΈΠΌΠ½ΡΠ΅ ΡΡΠ½ΠΊΡΠΈΠΈ
ΠΈΠ· callable-Π²ΡΡΠ°ΠΆΠ΅Π½ΠΈΠΉ.
ΠΠΎΠ²ΡΠΉ ΡΠΈΠ½ΡΠ°ΠΊΡΠΈΡ Π²ΡΡΠ΅ΡΠ½ΡΠ΅Ρ ΠΏΡΠ΅Π΄ΡΠ΄ΡΡΠΈΠΉ callable-ΡΠΈΠ½ΡΠ°ΠΊΡΠΈΡ ΡΠΎ ΡΡΡΠΎΠΊΠ°ΠΌΠΈ ΠΈ ΠΌΠ°ΡΡΠΈΠ²Π°ΠΌΠΈ.
ΠΡΠ΅ΠΈΠΌΡΡΠ΅ΡΡΠ²ΠΎ Π½ΠΎΠ²ΠΎΠ³ΠΎ ΡΠΈΠ½ΡΠ°ΠΊΡΠΈΡΠ° ΡΠΎΡΡΠΎΠΈΡ Π² Π΄ΠΎΡΡΡΠΏΠ½ΠΎΡΡΠΈ Π΄Π»Ρ ΡΡΠ°ΡΠΈΡΠ΅ΡΠΊΠΎΠ³ΠΎ Π°Π½Π°Π»ΠΈΠ·Π°
ΠΈ Π½Π°ΡΠ»Π΅Π΄ΠΎΠ²Π°Π½ΠΈΠΈ Π½ΠΎΠ²ΡΠΌ ΡΠΈΠ½ΡΠ°ΠΊΡΠΈΡΠΎΠΌ ΠΎΠ±Π»Π°ΡΡΠΈ Π²ΠΈΠ΄ΠΈΠΌΠΎΡΡΠΈ ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΡ
Π² ΡΠΎΡΠΊΠ΅
ΠΏΠΎΠ»ΡΡΠ΅Π½ΠΈΡ callable-Π²ΡΡΠ°ΠΆΠ΅Π½ΠΈΡ.
Π‘ΠΈΠ½ΡΠ°ΠΊΡΠΈΡ CallableExpr(...) ΡΠΎΠ·Π΄Π°ΡΡ ΠΎΠ±ΡΠ΅ΠΊΡ
Closure ΠΈΠ· Π²ΡΡΠ°ΠΆΠ΅Π½ΠΈΡ, Π΄ΠΎΡΡΡΠΏΠ½ΠΎΠ³ΠΎ Π΄Π»Ρ Π²ΡΠ·ΠΎΠ²Π°,
Π³Π΄Π΅ CallableExpr β ΡΠ»Π΅ΠΌΠ΅Π½Ρ ΡΠΈΠ½ΡΠ°ΠΊΡΠΈΡΠ°, ΠΊΠΎΡΠΎΡΡΠΉ ΠΏΡΠΈΠ½ΠΈΠΌΠ°Π΅Ρ Π²ΡΡΠ°ΠΆΠ΅Π½ΠΈΠ΅,
Π΄ΠΎΡΡΡΠΏΠ½ΠΎΠ΅ Π΄Π»Ρ ΠΏΡΡΠΌΠΎΠ³ΠΎ Π²ΡΠ·ΠΎΠ²Π° Π² ΡΠ΅ΡΠΌΠΈΠ½Π°Ρ
PHP-Π³ΡΠ°ΠΌΠΌΠ°ΡΠΈΠΊΠΈ:
ΠΡΠΈΠΌΠ΅Ρ #1 ΠΡΠΈΠΌΠ΅Ρ ΡΠΎΠ·Π΄Π°Π½ΠΈΡ ΠΏΠ΅ΡΠ²ΠΎΠΊΠ»Π°ΡΡΠ½ΡΡ
Π²ΡΠ·ΡΠ²Π°Π΅ΠΌΡΡ
Π·Π½Π°ΡΠ΅Π½ΠΈΠΉ ΡΠΈΠ½ΡΠ°ΠΊΡΠΈΡΠΎΠΌ Ρ ΠΌΠ½ΠΎΠ³ΠΎΡΠΎΡΠΈΠ΅ΠΌ
<?php
class Foo
{
public function method() {}
public static function staticmethod() {}
public function __invoke() {}
}
$obj = new Foo();
$classStr = 'Foo';
$methodStr = 'method';
$staticmethodStr = 'staticmethod';
$f1 = strlen(...);
$f2 = $obj(...); // ΠΡΠ·ΠΎΠ² ΠΎΠ±ΡΠ΅ΠΊΡΠ° ΠΊΠ°ΠΊ ΡΡΠ½ΠΊΡΠΈΠΈ
$f3 = $obj->method(...);
$f4 = $obj->$methodStr(...);
$f5 = Foo::staticmethod(...);
$f6 = $classStr::$staticmethodStr(...);
// Π’ΡΠ°Π΄ΠΈΡΠΈΠΎΠ½Π½ΡΠΉ ΡΠΈΠ½ΡΠ°ΠΊΡΠΈΡ callable-Π²ΡΡΠ°ΠΆΠ΅Π½ΠΈΠΉ ΡΠΎ ΡΡΡΠΎΠΊΠ°ΠΌΠΈ ΠΈ ΠΌΠ°ΡΡΠΈΠ²Π°ΠΌΠΈ
$f7 = 'strlen'(...);
$f8 = [$obj, 'method'](...);
$f9 = [Foo::class, 'staticmethod'](...);
ΠΠ°ΠΌΠ΅ΡΠ°Π½ΠΈΠ΅:
ΠΠΏΠ΅ΡΠ°ΡΠΎΡ ... β ΡΠ°ΡΡΡ ΡΠΈΠ½ΡΠ°ΠΊΡΠΈΡΠ°, Π° Π½Π΅ ΠΏΡΠΎΠΏΡΡΠΊ.
ΠΡΡΠ°ΠΆΠ΅Π½ΠΈΠ΅ CallableExpr(...) ΠΈ ΠΌΠ΅ΡΠΎΠ΄ Closure::fromCallable()
ΡΠ΅ΠΌΠ°Π½ΡΠΈΡΠ΅ΡΠΊΠΈ ΠΈΠ΄Π΅Π½ΡΠΈΡΠ½Ρ. ΠΠΎΡΡΠΎΠΌΡ Π² ΠΎΡΠ»ΠΈΡΠΈΠ΅ ΠΎΡ callable-ΡΠΈΠ½ΡΠ°ΠΊΡΠΈΡΠ°
ΡΠΎ ΡΡΡΠΎΠΊΠ°ΠΌΠΈ ΠΈ ΠΌΠ°ΡΡΠΈΠ²Π°ΠΌΠΈ, ΡΠΈΠ½ΡΠ°ΠΊΡΠΈΡ CallableExpr(...)
ΡΡΠΈΡΡΠ²Π°Π΅Ρ ΠΎΠ±Π»Π°ΡΡΡ Π²ΠΈΠ΄ΠΈΠΌΠΎΡΡΠΈ ΠΊΠΎΠ½ΡΠ΅ΠΊΡΡΠ°, Π² ΠΊΠΎΡΠΎΡΠΎΠΌ ΡΠΎΠ·Π΄Π°ΡΡ Π·Π°ΠΌΡΠΊΠ°Π½ΠΈΠ΅:
ΠΡΠΈΠΌΠ΅Ρ #2
Π‘ΡΠ°Π²Π½Π΅Π½ΠΈΠ΅ ΠΎΠ±Π»Π°ΡΡΠΈ Π²ΠΈΠ΄ΠΈΠΌΠΎΡΡΠΈ ΡΠΈΠ½ΡΠ°ΠΊΡΠΈΡΠ° CallableExpr(...)
ΠΈ ΡΡΠ°Π΄ΠΈΡΠΈΠΎΠ½Π½ΠΎΠ³ΠΎ callable-ΡΠΈΠ½ΡΠ°ΠΊΡΠΈΡΠ°
<?php
class Foo
{
public function getPrivateMethod()
{
return [$this, 'privateMethod'];
}
private function privateMethod()
{
echo __METHOD__, "\n";
}
}
$foo = new Foo();
$privateMethod = $foo->getPrivateMethod();
$privateMethod();
// Fatal error: Call to private method Foo::privateMethod() from global scope
// ΠΡΠΈΡΠΈΠ½Π° ΡΠ°ΡΠ°Π»ΡΠ½ΠΎΠΉ ΠΎΡΠΈΠ±ΠΊΠΈ ΡΠΎΡΡΠΎΠΈΡ Π² Π²ΡΠ·ΠΎΠ²Π΅ Π·Π°ΠΌΡΠΊΠ°Π½ΠΈΡ Π²Π½Π΅ ΠΊΠ»Π°ΡΡΠ° Foo,
// ΠΏΡΠΈ ΡΠΎΠΌ ΡΡΠΎ Π²ΠΈΠ΄ΠΈΠΌΠΎΡΡΡ ΠΌΠ΅ΡΠΎΠ΄Π° ΠΏΡΠΎΠ²Π΅ΡΡΠ΅ΡΡΡ Π² ΠΊΠΎΠ½ΡΠ΅ΠΊΡΡΠ΅ Π²ΡΠ·ΠΎΠ²Π°, Π° Π½Π΅ ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½ΠΈΡ
ΠΠ°ΠΌΠ΅ΡΠ°Π½ΠΈΠ΅:
Π‘ΠΈΠ½ΡΠ°ΠΊΡΠΈΡΠΎΠΌ Π½Π°ΠΏΠΎΠ΄ΠΎΠ±ΠΈΠ΅ new Foo(...) Π½Π΅Π»ΡΠ·Ρ ΡΠΎΠ·Π΄Π°ΡΡ ΠΎΠ±ΡΠ΅ΠΊΡ,
ΠΏΠΎΡΠΊΠΎΠ»ΡΠΊΡ ΡΠΈΠ½ΡΠ°ΠΊΡΠΈΡ new Foo() Π½Π΅ ΠΎΡΠ½ΠΎΡΠΈΡΡΡ ΠΊ Π²ΡΠ·ΠΎΠ²Π°ΠΌ.
ΠΠ°ΠΌΠ΅ΡΠ°Π½ΠΈΠ΅:
Π‘ΠΈΠ½ΡΠ°ΠΊΡΠΈΡ, ΠΊΠΎΡΠΎΡΡΠΉ ΡΠΎΠ·Π΄Π°ΡΡ ΠΎΠ±ΡΠ΅ΠΊΡΡ ΠΏΠ΅ΡΠ²ΠΎΠ³ΠΎ ΠΊΠ»Π°ΡΡΠ° ΠΈΠ· callable-Π²ΡΡΠ°ΠΆΠ΅Π½ΠΈΠΉ,
Π½Π΅Π»ΡΠ·Ρ ΠΊΠΎΠΌΠ±ΠΈΠ½ΠΈΡΠΎΠ²Π°ΡΡ
Ρ null-Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΡΠΌ ΠΎΠΏΠ΅ΡΠ°ΡΠΎΡΠΎΠΌ.
ΠΠ°ΠΆΠ΄Π°Ρ ΠΈΠ· ΡΠ»Π΅Π΄ΡΡΡΠΈΡ
ΡΡΡΠΎΠΊ Π²ΡΠ·ΡΠ²Π°Π΅Ρ ΠΎΡΠΈΠ±ΠΊΡ Π²ΡΠ΅ΠΌΠ΅Π½ΠΈ ΠΊΠΎΠΌΠΏΠΈΠ»ΡΡΠΈΠΈ: