Использование `$this` в анонимной функции в PHP до 5.4.0

В руководстве по PHP написано

Не возможно использовать $this из анонимной функции до PHP 5.4.0

на странице анонимных функций. Но я обнаружил, что могу заставить его работать, назначив $this к переменной и передачи переменной в use утверждение в определении функции.

$CI = $this;
$callback = function () use ($CI) {
    $CI->public_method();
};

Это хорошая практика?
Есть ли лучший способ доступа $this внутри анонимной функции с использованием PHP 5.3?

5 ответов

Решение

Он потерпит неудачу, когда вы попытаетесь вызвать защищенный или закрытый метод для него, потому что использование этого способа считается вызовом извне. Насколько я знаю, в 5.3 нет способа обойти эту проблему, но в PHP 5.4 он будет работать, как и ожидалось, из коробки:

class Hello {

    private $message = "Hello world\n";

    public function createClosure() {
        return function() {
            echo $this->message;
        };
    }

}
$hello = new Hello();
$helloPrinter = $hello->createClosure();
$helloPrinter(); // outputs "Hello world"

Более того, вы сможете изменить, на что указывает $this во время выполнения, для функций анонима (повторное закрытие):

class Hello {

    private $message = "Hello world\n";

    public function createClosure() {
        return function() {
            echo $this->message;
        };
    }

}

class Bye {

    private $message = "Bye world\n";

}

$hello = new Hello();
$helloPrinter = $hello->createClosure();

$bye = new Bye();
$byePrinter = $helloPrinter->bindTo($bye, $bye);
$byePrinter(); // outputs "Bye world"

По сути, функции anonymus будут иметь метод bindTo(), где первый параметр может использоваться для указания того, на что указывает $this, а второй параметр определяет, каким должен быть уровень видимости. Если вы опустите второй параметр, видимость будет похожа на вызов извне, например. только общедоступные свойства могут быть доступны. Также обратите внимание на то, как работает bindTo, он не изменяет исходную функцию, а возвращает новую.

Не всегда полагайтесь на то, что PHP передает объекты по ссылке, когда вы сами присваиваете ссылку, поведение не такое, как в большинстве ОО-языков, где изменяется исходный указатель.

ваш пример:

$CI = $this;
$callback = function () use ($CI) {
$CI->public_method();
};

должно быть:

$CI = $this;
$callback = function () use (&$CI) {
$CI->public_method();
};

ЗАМЕЧАНИЕ: ССЫЛКИ "&" и $CI должны быть назначены после того, как будут выполнены последние вызовы, опять же, в противном случае вы можете получить непредсказуемый вывод, в PHP доступ к ссылке не всегда совпадает с доступом к исходному классу - если это имеет смысл.

http://php.net/manual/en/language.references.pass.php

Это нормальный способ, которым это было сделано.
Кстати, попробуйте удалить & это должно работать без этого, так как объекты передаются по ссылке любым способом.

Это отлично. Я должен подумать, что вы могли бы сделать это также:

$CI = $this;

... поскольку присваивания, включающие объекты, всегда будут копировать ссылки, а не целые объекты.

Это нормально, если вы передаете по ссылке, это правильный способ сделать это. Если вы используете PHP 5, вам не нужно & символ перед $this как это всегда будет проходить по ссылке независимо.

Другие вопросы по тегам