Это пробел, который PHP (и другие языки программирования) не говорят прямо в своих книгах: вы можете иметь два раза одно и то же имя переменной (в вашем случае $error
), но даже одно и то же не идентифицируйте одну и ту же переменную (адресуйте одну и ту же память).
Поначалу это может показаться немного прямолинейным, но это становится более разумным, когда речь идет о структурировании более крупной программы, поскольку значительные все хорошо понятные имена переменных ограничены, поэтому создание каждой переменной по ее имени, доступной в глобальном пространстве имен, будет довольно быстро испортил весь программный код.
Итак, я вижу несколько путей, как с этим справиться, если вам интересно (если нет, то здесь некоторые существующие вопросы и ответы, касающиеся ключевого слова static
в PHP-функции ).
Первый довольно ленивый и, скорее всего, небезопасный с точки зрения обработки данных, поэтому весь программный код должен быть очень точным, чтобы его можно было безопасно использовать: «не переопределяйте массив, просто используйте его глобально ». Вы можете сделать это с помощью глобальной переменной.
Инициализация должна быть сделана в начале приложения:
$GLOBALS['errors'] = [];
Затем вы можете добавлять в эту переменную новые записи всякий раз, когда чувствуете, что это необходимо:
$GLOBALS['errors'][] = $error;
И если вам нужно снова получить список ошибок, просто прочитайте его:
var_dump($GLOBALS['errors']);
На самом деле это имя глобальной переменной errors
. Глобальные переменные являются мощными, но и дорогими в их обслуживании, поскольку любой код может - по назначению или по ошибке - сбрасывать все ошибки, например, или даже более резко, превращать массив в строку, и в следующий раз некоторый код захочет добавить новую запись, произойдет сбой .
Так как же может выглядеть решение, не использующее глобальную переменную? За счет стоимости (и с пользой) более контролируемого доступа к вашей коллекции ошибок вы можете создать объект, представляющий этот список ошибок, и передавать его туда, где бы вы ни хотели добавить ошибку.
Но прежде чем показать экземпляр объекта, я сначала покажу пример статического класса, поскольку он может быть ближе к вашей ментальной модели с функцией и ее статической переменной-
Реализованный со статическими модификаторами, вы можете создать недоступную глобальную переменную (private static global), которая доступна только функции, которая добавляет к ней сообщения (и другой статической функции того же класса).
Тогда легко добавить еще одну глобально доступную функцию, которая сможет возвращать содержимое этой переменной:
final class Errors
{
private static $errors = [];
public static function add(string $error): void
{
self::$errors[] = $error;
}
public static function get(): array
{
return self::$errors;
}
}
Этот класс предоставляет ограниченный доступ к статически недоступной в противном случае статической переменной Errors::$errors
.
Он автоматически инициализирует момент загрузки этого определения класса (например, через include
/ require
или автозагрузчик), новые ошибки могут быть добавлены через:
Errors::add($error);
И ошибки могут быть считаны через:
var_dump(Errors::get());
Теперь это более безопасно для использования в качестве глобальной переменной, однако по-прежнему существует только один глобальный список ошибок, и каждая часть кода может получить к нему доступ через идентификатор класса Errors::...
(имя класса).
Таким образом, проблема, заключающаяся в том, что через некоторое время используются все используемые имена, не решается этим.
Чтобы предотвратить превращение класса из статического в нестатический, необходимо перейти от глобальных статических функций к экземплярам объекта. Это легко сделать, в основном просто удаляя статические модификаторы и переключаясь с self::$
на $this->
. Это легко, я делаю весь пример сразу:
final class Errors
{
private $errors = [];
public function add(string $error): void
{
$this->errors[] = $error;
}
public function get(): array
{
return $this->errors;
}
}
Теперь, чтобы этот класс заработал, ему нужно еще немного поработать с
лучший контроль. Прежде всего требуется инициализация:
$errors = new Errors;
После этого сбор ошибок должен быть передан во все места, где необходимо добавить ошибку:
$errors->add($error);
А если хотите, прочитайте все ошибки, собранные на данный момент:
var_dump($errors->get());
Этот последний вариант требует, чтобы вы управляли (и, следовательно, думали) о том, какие части вашего кода должны иметь доступ к какому-либо конкретному набору ошибок (так как вы можете создать более одного). Так что это больше работы на первый взгляд, однако в долгосрочной перспективе многое упрощает. Вы можете изменить ошибки
коллекция (например, хранить в файле рядом с массивом) без необходимости менять все места, где было добавлено сообщение.
Вы можете предоставить другой объект сбора ошибок для разных целей, например, только в сценарии тестирования или в подмодуле вашей программы.
Так что это также дает большую гибкость (просто начните с минимума).
Статический класс в середине теперь может показаться священным Граалем, но я бы сказал, что он только посредственный и значительно ускоряет ваш код, поскольку он не такой мощный, как глобальные переменные, но и потребляет имя, которое не может быть легко изменено при увеличении размера вашего приложения.
Если использование понятно, глобальные переменные могут быть мощным инструментом, а также статическим доступом. Но дьявол кроется в деталях и на более дифференцированном уровне, часто довольно полезно использовать объекты в значении объектно-ориентированного программирования.
глобальная переменная - объект памяти
переменная объекта - объект программирования (дает вам больше контроля через определение класса для управления изменениями во времени, код и данные формируют свои собственные единицы)