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 !")

3

Решение

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

Другие решения

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

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

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

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

2

это немного странно для него, но если вы используете функцию внутри функции, то, конечно, действуют некоторые доводчики.
Вы можете иметь подобную проблему в 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 foo () {

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

bar($this,"world !");

}
0

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

<?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
По вопросам рекламы [email protected]