Закрытие PHP: используйте ключевое слово с определением функции: аргумент объекта для использования: параметр не скопирован

Следующий код является слегка измененной версией примера из

Руководство по PHP -> Справочник по языку -> Функции -> Анонимные функции.

В примере упоминается, но не объясняется, почему вы не можете передать объект PHP по значению
в список аргументов после использования ключевого слова в функции. В частности, почему нет
объект передается по значению в списке параметров использования, как в следующем коде
скопировать в $ broken анонимную функцию, как это можно сделать со скалярными значениями?

Вот код:

class MyClass {

function doSomething() { echo "HELLO WORLD\n"; }

}

$myInstance = null;

$broken = function() use ($myInstance) {
if(!empty($myInstance)) $myInstance->doSomething();
else echo "\$myInstance is empty.\n";
var_dump($myInstance); // NULL
};

$working = function() use (&$myInstance) {
if(!empty($myInstance)) $myInstance->doSomething();
else print "\$myInstance is empty.\n";
};

$myInstance = new MyClass();

$myInstance->doSomething();    // Outputs HELLO WORLD.
$broken();                     // Outputs $myInstance is empty. NULL
$working();                    // Outputs HELLO WORLD.

Благодарю.


Это обновление моего поста после ответа, полученного от Валентина Родыгина.
Если $ myInstance = null; строка закомментирована, я получаю следующую ошибку:

Notice: Undefined variable: myInstance in C:\xampp\htdocs\myexamples\use.php on line 11

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

Благодарю.

1

Решение

Давайте внимательнее посмотрим на ваш код.

$myInstance = null;
$broken = function() use ($myInstance) {
if(!empty($myInstance)) $myInstance->doSomething();
else echo "\$myInstance is empty.\n";
var_dump($myInstance); // NULL
};

На данный момент вы уже создали замыкание и передали туда копия переменной, и это NULL.

$working = function() use (&$myInstance) {
if(!empty($myInstance)) $myInstance->doSomething();
else print "\$myInstance is empty.\n";
};

И здесь вы передали ссылку, поэтому позже, когда вы создали экземпляр $ myInstance, он стал доступен в закрытии.

2

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

Других решений пока нет …