Во-первых, извините за мой английский, я не являюсь носителем языка и извините, если он выглядит грубым, я впервые публикую на этом сайте.
Моя проблема довольно проста, я думаю. Допустим, у нас есть:
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 !")
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()
используется для «публикации» защищенных / частных свойств, чтобы сделать их доступными в закрытии.
На самом деле, $this
относится к $qux
когда вызывается в этом контексте.
Вы не можете использовать $this
в контекстах, отличных от метода объекта, поэтому, если вы взяли что-то вроде этого:
function test() {
echo $this->baz;
}
Это не сработает, независимо от того, что вы делаете.
это немного странно для него, но если вы используете функцию внутри функции, то, конечно, действуют некоторые доводчики.
Вы можете иметь подобную проблему в 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 !");
}
Если я понимаю, чего вы пытаетесь достичь, это может быть так:
<?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
свойства потерпят неудачу.