PHP-эквивалент привязки JavaScript


Во-первых, извините за мой английский, я не являюсь носителем языка, и извините, если это выглядит грубо, это первый раз, когда я публикую на этом сайте. Я думаю, что моя проблема довольно проста. Допустим, у нас есть:

class A {

    function foo() {

        function bar ($arg){
            echo $this->baz, $arg;
        }

        bar("world !");

    }

    protected $baz = "Hello ";

}

$qux = new A;

$qux->foo();

В этом примере "$this" явно не относится к моему объекту "$qux".

Как мне сделать, чтобы он соответствовал "$qux"?

Как может быть в JavaScript : bar.bind(this, "world !")

Author: georg, 2014-11-19

4 answers

PHP не имеет вложенных функций, поэтому в вашем примере bar по сути является глобальным. Вы можете достичь того, чего хотите, используя замыкания (=анонимные функции), которые поддерживают привязку начиная с PHP 5.4:

class A {
    function foo() {
        $bar = function($arg) {
            echo $this->baz, $arg;
        };
        $bar->bindTo($this);
        $bar("world !");
    }
    protected $baz = "Hello ";
}

$qux = new A;
$qux->foo();

UPD: однако bindTo($this) не имеет особого смысла, потому что замыкания автоматически наследуют this из контекста (опять же, в 5.4). Таким образом, ваш пример может быть простым:

    function foo() {
        $bar = function($arg) {
            echo $this->baz, $arg;
        };
        $bar("world !");
    }

UPD2: для php 5.3 - это, похоже, возможно только с таким уродливым взломом, как это:

class A {
    function foo() {
        $me = (object) get_object_vars($this);
        $bar = function($arg) use($me) {
            echo $me->baz, $arg;
        };
        $bar("world !");
    }
    protected $baz = "Hello ";
}

Здесь get_object_vars() используется для "публикации" защищенных/частных свойств, чтобы сделать их доступными в рамках закрытия.

 3
Author: georg, 2014-11-19 15:15:45

На самом деле, $this действительно ссылается на $qux, когда вызывается в этом контексте.

Вы не можете использовать $this в контекстах, отличных от метода объекта, поэтому, если вы взяли что-то вроде этого:

function test() {
    echo $this->baz;
}

Это не сработает, что бы вы ни делали.

 2
Author: Madara Uchiha, 2014-11-19 10:39:09

Это немного странно, но если вы используете функцию внутри функции, то, конечно, действуют некоторые закрывающие устройства. у вас может возникнуть аналогичная проблема в javascript. Я бы посоветовал вообще их не использовать, но если по какой-то причине вы не хотите, то я бы попробовал вот так (не проверено):

class A {

    function foo() {

        $that = $this;
        function bar ($arg){
            echo $that->baz, $arg;
        }

        bar("world !");

    }

    protected $baz = "Hello ";

}

$qux = new A;

$qux->foo();

ОБНОВИТЬ если вложенная функция действует как глобальная функция, то вы можете передать свой объект в качестве параметра, если вам нужно его использовать:

Функция фу() {

        function bar ($o,$arg){
            echo $o->baz, $arg;
        }

        bar($this,"world !");

    }
 0
Author: Asped, 2014-11-19 10:49:10

Если я понимаю, чего вы пытаетесь достичь, это может быть так:

<?php
class Foo {

  public $prop;

  public function __construct($prop) {
    $this->prop = $prop;
  }

  public function __call($name, $arguments) {
    if (!isset($this->$name)) {
      throw new InvalidArgumentException("No such property: $name");
    }

    if (! $this->{$name} instanceof Closure) {
      throw new InvalidArgumentException("{$name} is not a closure");
    }

    $c = $this->{$name}->bindTo($this);
    return $c(...$arguments);
  }
}

$f = new Foo("bar");
$f->bar = function ($arg) {
  print_r([$arg, $this->prop]);
};

$f->bar("A");
?>

Таким образом, вы можете по существу исправить любую функцию в классе и вызвать ее так, как если бы она была локальной, даже включая использование $this. Однако есть два ограничения:

  • это кажется бессмысленным, так как черты доступны, за исключением случаев, когда вы добавляете действительно динамически определенные в немодифицируемый пакет
  • хотя закрытие может получить доступ к свойствам на $this, оно все еще является внешним по отношению к объект, поэтому может получить доступ только к общедоступным свойствам. Попытка получить доступ protected/private свойства выйдут из строя.
 0
Author: FGM, 2018-03-26 07:39:01