я пытаюсь играть с php5.3 и закрытием.
Я вижу здесь (Список 7. Закрытие в объекте: http://www.ibm.com/developerworks/opensource/library/os-php-5.3new2/index.html), что возможно использовать $this в функции обратного вызова, но это не. Таким образом, я пытаюсь дать $this как переменную использования:
$self = $this;
$foo = function() use($self) { //do something with $self }
Таким образом использовать тот же пример:
class Dog
{
private $_name;
protected $_color;
public function __construct($name, $color)
{
$this->_name = $name;
$this->_color = $color;
}
public function greet($greeting)
{
$self = $this;
return function() use ($greeting, $self) {
echo "$greeting, I am a {$self->_color} dog named {$self->_name}.";
};
}
}
$dog = new Dog("Rover","red");
$dog->greet("Hello");
Output:
Hello, I am a red dog named Rover.
В первую очередь, этот пример не печатает строку, но возвращает функцию, но это не моя проблема.
Во-вторых, я не могу получить доступ к частному или защищенному, потому что функция обратного вызова является глобальной функцией а не в контексте от объекта Собаки. Tha't моя проблема. Это совпадает с:
function greet($greeting, $object) {
echo "$greeting, I am a {$self->_color} dog named {$self->_name}.";
}
И я хочу:
public function greet($greeting) {
echo "$greeting, I am a {$self->_color} dog named {$self->_name}.";
}
Который является от Собаки и не глобален.
Что ж, логично, что вы не можете получить доступ к закрытым и защищенным полям объекта. И если явно передать $ self
вашей функции, она будет рассматриваться как обычный объект.
Вы должны создать геттеры, чтобы получить доступ к этим значениям, например:
class Dog
{
private $_name;
protected $_color;
public function __construct($name, $color)
{
$this->_name = $name;
$this->_color = $color;
}
public function getName() {
return $this->_name;
}
public function getColor() {
return $this->_color;
}
public function greet($greeting)
{
$self = $this;
return function() use ($greeting, $self) {
echo "$greeting, I am a {$self->getColor()} dog named {$self->getName()}.";
};
}
}
Вы должны создать геттер (и сеттеры) в любом случае, в отношении инкапсуляции .
Еще одно примечание: статья, на которую вы ссылаетесь, была опубликована до того, как была выпущена финальная версия PHP 5.3. Возможно, эта неявная передача объекта была удалена.
Ну, вся причина, по которой вы не можете использовать $ this, заключается в том, что замыкание является объектом в фоновом режиме (класс Closure) .
Есть два способа обойти это. Во-первых, добавьте метод __invoke (что вызывается, если вы вызываете $ obj ()) ..
class Dog {
public function __invoke($method) {
$args = func_get_args();
array_shift($args); //get rid of the method name
if (is_callable(array($this, $method))) {
return call_user_func_array(array($this, $method), $args);
} else {
throw new BadMethodCallException('Unknown method: '.$method);
}
}
public function greet($greeting) {
$self = $this;
return function() use ($greeting, $self) {
$self('do_greet', $greeting);
};
}
protected function do_greet($greeting) {
echo "$greeting, I am a {$this->_color} dog named {$this->_name}.";
}
}
Если вы хотите, чтобы закрытие не изменялось, если вы изменяете объект хоста, вы можете просто изменить функцию возврата на что-то вроде:
public function greet($greeting) {
$self = (clone) $this;
return function() use ($greeting, $self) {
$self('do_greet', $greeting);
};
}
Другой вариант - предоставить общий получатель:
class Dog {
public function __get($name) {
return isset($this->$name) ? $this->$name : null;
}
}
Для получения дополнительной информации см .: http://www.php.net/manual/en/language.oop5.magic.php