Closure::bind

(PHP 5 >= 5.4.0, PHP 7, PHP 8)

Closure::bind β€” Π”ΡƒΠ±Π»ΠΈΡ€ΡƒΠ΅Ρ‚ Π·Π°ΠΌΡ‹ΠΊΠ°Π½ΠΈΠ΅ ΠΈ привязываСт копию замыкания ΠΊ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Ρƒ ΠΈ области видимости класса статичСски

ОписаниС

public static function Closure::bind(Closure $closure, ?object $newThis, object|string|null $newScope = "static"): ?Closure

ΠœΠ΅Ρ‚ΠΎΠ΄ прСдставляСт ΡΡ‚Π°Ρ‚ΠΈΡ‡Π΅ΡΠΊΡƒΡŽ Π²Π΅Ρ€ΡΠΈΡŽ ΠΌΠ΅Ρ‚ΠΎΠ΄Π° Closure::bindTo(), описаниС ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ Π΄Π°Ρ‘Ρ‚ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½ΡƒΡŽ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ.

Бписок ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠ²

closure

Анонимная функция, ΠΊΠΎΡ‚ΠΎΡ€ΡƒΡŽ ΠΌΠ΅Ρ‚ΠΎΠ΄ свяТСт с ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠΌ.

newThis

ΠžΠ±ΡŠΠ΅ΠΊΡ‚, ΠΊ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌΡƒ трСбуСтся ΠΏΡ€ΠΈΠ²ΡΠ·Π°Ρ‚ΡŒ Π°Π½ΠΎΠ½ΠΈΠΌΠ½ΡƒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ, ΠΈΠ»ΠΈ null, Ссли привязка Π½Π΅ трСбуСтся.

newScope

НазваниС класса, ΠΊ области видимости ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ трСбуСтся ΠΏΡ€ΠΈΠ²ΡΠ·Π°Ρ‚ΡŒ Π·Π°ΠΌΡ‹ΠΊΠ°Π½ΠΈΠ΅, ΠΈΠ»ΠΈ ΠΊΠ»ΡŽΡ‡Π΅Π²ΠΎΠ΅ слово 'static' для сохранСния Π·Π°ΠΌΡ‹ΠΊΠ°Π½ΠΈΠ΅ΠΌ Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ области видимости. ΠŸΡ€ΠΈ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡Π΅ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° контСкст класса опрСдСляСтся Ρ‚ΠΈΠΏΠΎΠΌ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°. ΠŸΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ опрСдСляСт Π²ΠΈΠ΄ΠΈΠΌΠΎΡΡ‚ΡŒ Π·Π°Ρ‰ΠΈΡ‰Ρ‘Π½Π½Ρ‹Ρ… ΠΈ Π·Π°ΠΊΡ€Ρ‹Ρ‚Ρ‹Ρ… Ρ‡Π»Π΅Π½ΠΎΠ² ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°, ΠΊ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌΡƒ привязываСтся Π·Π°ΠΌΡ‹ΠΊΠ°Π½ΠΈΠ΅. НСльзя ΠΏΠ΅Ρ€Π΅Π΄Π°Π²Π°Ρ‚ΡŒ Π² ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ Π½Π°Π·Π²Π°Π½ΠΈΠ΅ ΠΈΠ»ΠΈ экзСмпляр ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° Π²Π½ΡƒΡ‚Ρ€Π΅Π½Π½Π΅Π³ΠΎ PHP-класса.

Π’ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌΡ‹Π΅ значСния

ΠœΠ΅Ρ‚ΠΎΠ΄ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Π½ΠΎΠ²Ρ‹ΠΉ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ класса Closure ΠΈΠ»ΠΈ null, Ссли Π²ΠΎΠ·Π½ΠΈΠΊΠ»Π° ошибка.

ΠŸΡ€ΠΈΠΌΠ΅Ρ€Ρ‹

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ #1 ΠŸΡ€ΠΈΠΌΠ΅Ρ€ привязки замыкания ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠΌ Closure::bind()

<?php

class A
{
private static
$sfoo = 1;
private
$ifoo = 2;
}

$cl1 = static function () {
return
A::$sfoo;
};

$cl2 = function () {
return
$this->ifoo;
};

$bcl1 = Closure::bind($cl1, null, 'A');
$bcl2 = Closure::bind($cl2, new A(), 'A');

echo
$bcl1(), "\n";
echo
$bcl2(), "\n";

?>

Π’Ρ‹Π²ΠΎΠ΄ ΠΏΡ€ΠΈΠ²Π΅Π΄Ρ‘Π½Π½ΠΎΠ³ΠΎ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π° Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΠΎΡ…ΠΎΠΆ Π½Π°:

1
2

Π‘ΠΌΠΎΡ‚Ρ€ΠΈΡ‚Π΅ Ρ‚Π°ΠΊΠΆΠ΅

οΌ‹Π”ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ

ΠŸΡ€ΠΈΠΌΠ΅Ρ‡Π°Π½ΠΈΡ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΉ 2 notes

up
97
Vincius Krolow ΒΆ
13 years ago
With this class and method, it's possible to do nice things, like add methods on the fly to an object.

MetaTrait.php
<?php
trait MetaTrait
{
    
    private $methods = array();
 
    public function addMethod($methodName, $methodCallable)
    {
        if (!is_callable($methodCallable)) {
            throw new InvalidArgumentException('Second param must be callable');
        }
        $this->methods[$methodName] = Closure::bind($methodCallable, $this, get_class());
    }
 
    public function __call($methodName, array $args)
    {
        if (isset($this->methods[$methodName])) {
            return call_user_func_array($this->methods[$methodName], $args);
        }
 
        throw RunTimeException('There is no method with the given name to call');
    }
 
}
?>

test.php
<?php
require 'MetaTrait.php';
 
class HackThursday {
    use MetaTrait;
 
    private $dayOfWeek = 'Thursday';
 
}
 
$test = new HackThursday();
$test->addMethod('when', function () {
    return $this->dayOfWeek;
});
 
echo $test->when();

?>
up
11
potherca at hotmail dot com ΒΆ
11 years ago
If you need to validate whether or not a closure can be bound to a PHP object, you will have to resort to using reflection.

<?php

/**
 * @param \Closure $callable
 *
 * @return bool
 */
function isBindable(\Closure $callable)
{
    $bindable = false;

    $reflectionFunction = new \ReflectionFunction($callable);
    if (
        $reflectionFunction->getClosureScopeClass() === null
        || $reflectionFunction->getClosureThis() !== null
    ) {
        $bindable = true;
    }

    return $bindable;
}
?>