Статический массив в функции PHP не работает - PullRequest
0 голосов
/ 29 апреля 2018

PHP - Тестирование простой функции со статической переменной массива. Я предполагаю, что статическая переменная, объявленная в функции, сделает ее доступной вне функции.

Эта функция просто принимает сообщение и добавляет его в массив ошибок [], а затем может использовать этот список ошибок [] вне функции.

Я получаю сообщение об ошибке: «Примечание: неопределенная переменная: ошибки в .... в строке 10»

В строке 10 указан код «print_r ($ errors);»

function addErrors($errmessage){
    static $errors = array();
    $errors[] = $errmessage; 
}
addErrors('test1');
addErrors('test2');
print_r($errors);

Ваш вклад приветствуется!

Ответы [ 4 ]

0 голосов
/ 29 апреля 2018

Это пробел, который 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());

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

Вы можете предоставить другой объект сбора ошибок для разных целей, например, только в сценарии тестирования или в подмодуле вашей программы.

Так что это также дает большую гибкость (просто начните с минимума).

Статический класс в середине теперь может показаться священным Граалем, но я бы сказал, что он только посредственный и значительно ускоряет ваш код, поскольку он не такой мощный, как глобальные переменные, но и потребляет имя, которое не может быть легко изменено при увеличении размера вашего приложения.

Если использование понятно, глобальные переменные могут быть мощным инструментом, а также статическим доступом. Но дьявол кроется в деталях и на более дифференцированном уровне, часто довольно полезно использовать объекты в значении объектно-ориентированного программирования.

  • глобальная переменная - объект памяти

  • переменная объекта - объект программирования (дает вам больше контроля через определение класса для управления изменениями во времени, код и данные формируют свои собственные единицы)

0 голосов
/ 29 апреля 2018

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

Вот пример, как добиться того, что вы пытаетесь сделать:

PHP 7 <: </h3> <?php /** * @param string|null the error message to add or null * @return array|null returns all errors if provided with null */ function errors($error = null) { static $errors = []; if($error !== null) { $errors[] = $error; return null; } else { return $errors; } } errors('Error !'); errors('Another !'); print_r(errors()); PHP 7> =:

<?php

function errors(string $error = null): ?array {
   static $errors = [];
   if($error !== null) {
       $errors[] = $error;
       return null;
   } else {
       return $errors;
   }
}

errors('Error !');
errors('Another !');
print_r(errors());
0 голосов
/ 29 апреля 2018

Вы определяете переменную $errors внутри области действия функции, вне области ее не будет.

Статический означает только то, что он будет создан один раз в этом случае, а не то, что он доступен вне области видимости, ключевое слово global может вам помочь, но, честно говоря, я бы рекомендовал другой подход (глобальный - это плохая практика ).

Вы можете вернуть массив ошибок из метода:

function addErrors($err) {
  static $errors = [];
  $errors[] = $err;
  return $errors;
}

Возможно, лучшим способом было бы создать класс:

class ErrorHandler {
  private static $errors = [];

  public static function addError($error) {
    self::$errors[] = $error;
  } 

  public static function getErrors() {
    return self::$errors;
  }

}

Тогда используйте его как:

 ErrorHandler::addError('error');
 print_r(ErrorHandler::getErrors());
0 голосов
/ 29 апреля 2018

Из документации:

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

Чтобы сделать переменную доступной вне области действия функции, вместо этого можно использовать ключевое слово global:

function addErrors($errmessage){
   global $errors;
   $errors[] = $errmessage; 
}

Ссылки

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...