Аварийный менеджер команд разработки
7,7
рейтинг
5 июня 2015 в 14:50

Разработка → Готовимся к собеседованию по PHP: ключевое слово «static» tutorial

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

image

Попробуем разобрать «по косточкам» один из таких вопросов — что значит слово «static» в PHP и зачем оно применяется?

Ключевое слово static имеет в PHP три различных значения. Разберем их в хронологическом порядке, как они появлялись в языке.

Значение первое — статическая локальная переменная


function foo() {
  $a = 0;
  echo $a;
  $a = $a + 1;
}

foo(); // 0
foo(); // 0
foo(); // 0


В PHP переменные локальны. Это значит, что переменная, определенная и получившая значение внутри функции (метода), существует только во время выполнения этой функции (метода). При выходе из метода локальная переменная уничтожается, а при повторном входе — создается заново. В коде выше такой локальной переменной является переменная $a — она существует только внутри функции foo() и каждый раз при вызове этой функции создается заново. Инкремент переменной в этом коде бессмысленен, поскольку на следующей же строчке кода функция закончит свою работу и значение переменной будет потеряно. Сколько бы раз мы не вызвали функцию foo(), она всегда будет выводить 0…

Однако всё меняется, если мы перед присваиванием поставим ключевое слово static:

function foo() {
  static $a = 0;
  echo $a;
  $a = $a + 1;
}

foo(); // 0
foo(); // 1
foo(); // 2


Ключевое слово static, написанное перед присваиванием значения локальной переменной, приводит к следующим эффектам:
  1. Присваивание выполняется только один раз, при первом вызове функции
  2. Значение помеченной таким образом переменной сохраняется после окончания работы функции
  3. При последующих вызовах функции вместо присваивания переменная получает сохраненное ранее значение

Такое использование слова static называется статическая локальная переменная.

Подводные камни статических переменных

Разумеется, как всегда в PHP, не обходится без «подводных камней».

Камень первый — статической переменной присваивать можно только константы или константные выражения. Вот такой код:
static $a = bar();

с неизбежностью приведет к ошибке парсера. К счастью, начиная с версии 5.6 стало допустимым присвоение не только констант, но и константных выражений (например — «1+2» или "[1, 2, 3]"), то есть таких выражений, которые не зависят от другого кода и могут быть вычислены на этапе компиляции

Камень второй — методы существуют в единственном экземпляре.
Тут всё чуть сложнее. Для понимания сути приведу код:
class A {
  public function foo() {
    static $x = 0;
    echo ++$x;
  }
}

$a1 = new A;
$a2 = new A;

$a1->foo(); // 1
$a2->foo(); // 2
$a1->foo(); // 3
$a2->foo(); // 4

Вопреки интуитивному ожиданию «разные объекты — разные методы» мы наглядно видим на этом примере, что динамические методы в PHP «не размножаются». Даже если у нас будет сто объектов этого класса, метод будет существовать лишь в одном экземпляре, просто при каждом вызове в него будет пробрасываться разный $this.

Такое поведение может быть неожиданным для неподготовленного к нему разработчика и послужить источником ошибок. Нужно заметить, что наследование класса (и метода) приводит к тому, что всё-таки создается новый метод:

class A {
  public function foo() {
    static $x = 0;
    echo ++$x;
  }
}

class B extends A {
}

$a1 = new A;
$b1 = new B;

$a1->foo(); // 1
$b1->foo(); // 1
$a1->foo(); // 2
$b1->foo(); // 2


Вывод: динамические методы в PHP существуют в контексте классов, а не объектов. И только лишь в рантайме происходит подстановка "$this = текущий_объект"

Значение второе — статические свойства и методы классов


В объектной модели PHP существует возможность задавать свойства и методы не только для объектов — экземпляров класса, но и для класса в целом. Для этого тоже служит ключевое слово static:

class A {
  public static $x = 'foo';
  public static function test() {
    return 42;
  }
}

echo A::$x; // 'foo'
echo A::test(); // 42

Для доступа к таким свойствам и методам используются конструкции с двойным двоеточием («Paamayim Nekudotayim»), такие как ИМЯ_КЛАССА::$имяПеременной и ИМЯ_КЛАССА:: имяМетода().

Само собой разумеется, что у статических свойств и статических методов есть свои особенности и свои «подводные камни», которые нужно знать.

Особенность первая, банальная — нет $this. Собственно это проистекает из самого определения статического метода — поскольку он связан с классом, а не объектом, в нём недоступна псевдопеременная $this, указывающая в динамических методах на текущий объект. Что совершенно логично.

Однако, нужно знать, что в отличие от других языков, PHP не определяет ситуацию «в статическом методе написано $this» на этапе парсинга или компиляции. Подобная ошибка может возникнуть только в рантайме, если вы попытаетесь выполнить код с $this внутри статического метода.

Код типа такого:
class A {
  public $id = 42;
  static public function foo() {
    echo $this->id;
  }
}

не приведет ни к каким ошибкам, до тех пор, пока вы не попытаетесь использовать метод foo() неподобающим образом:
$a = new A;
$a->foo();
(и сразу получите «Fatal error: Using $this when not in object context»)

Особенность вторая — static не аксиома!
class A {
  static public function foo() {
    echo 42;
  }
}

$a = new A;
$a->foo();

Вот так, да. Статический метод, если он не содержит в коде $this, вполне можно вызывать в динамическом контексте, как метод объекта. Это не является ошибкой в PHP.

Обратное не совсем верно:
class A {
  public function foo() {
    echo 42;
  }
}

A::foo();

Динамический метод, не использующий $this, можно выполнять в статическом контексте. Однако вы получите предупреждение «Non-static method A::foo() should not be called statically» уровня E_STRICT. Тут решать вам — или строго следовать стандартам кода, или подавлять предупреждения. Первое, разумеется, предпочтительнее.

И кстати, всё написанное выше относится только к методам. Использование статического свойства через "->" невозможно и ведет к фатальной ошибке.

Значение третье, кажущееся самым сложным — позднее статическое связывание


Разработчики языка PHP не остановились на двух значениях ключевого слова «static» и в версии 5.3 добавили еще одну «фичу» языка, которая реализована тем же самым словом! Она называется «позднее статическое связывание» или LSB (Late Static Binding).

Понять суть LSB проще всего на несложных примерах:

class Model {
  public static $table = 'table';
  public static function getTable() {
    return self::$table;
  }
}

echo Model::getTable(); // 'table'

Ключевое слово self в PHP всегда значит «имя класса, где это слово написано». В данном случае self заменяется на класс Model, а self::$table — на Model::$table.
Такая языковая возможность называется «ранним статическим связыванием». Почему ранним? Потому что связывание self и конкретного имени класса происходит не в рантайме, а на более ранних этапах — парсинга и компиляции кода. Ну а «статическое» — потому что речь идет о статических свойствах и методах.

Немного изменим наш код:

class Model {
  public static $table = 'table';
  public static function getTable() {
    return self::$table;
  }
}

class User extends Model {
  public static $table = 'users';
}

echo User::getTable(); // 'table'


Теперь вы понимаете, почему PHP ведёт себя в этой ситуации неинтуитивно. self был связан с классом Model тогда, когда о классе User еще ничего не было известно, поэтому и указывает на Model.

Как быть?

Для решения этой дилеммы был придуман механизм связывания «позднего», на этапе рантайма. Работает он очень просто — достаточно вместо слова «self» написать «static» и связь будет установлена с тем классом, который вызывает данный код, а не с тем, где он написан:
class Model {
  public static $table = 'table';
  public static function getTable() {
    return static::$table;
  }
}

class User extends Model {
  public static $table = 'users';
}

echo User::getTable(); // 'users'


Это и есть загадочное «позднее статическое связывание».

Нужно отметить, что для большего удобства в PHP кроме слова «static» есть еще специальная функция get_called_class(), которая сообщит вам — в контексте какого класса в данный момент работает ваш код.

Удачных собеседований!

Список полезных ссылок на мануал:
Альберт Степанцев @AlexLeonov
карма
151,0
рейтинг 7,7
Аварийный менеджер команд разработки
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (68)

  • 0
    Все становится просто супер интуитивно понятным, если понять, что значит static:
    — привязка к «объекту» класса, а его не его реализующего объекта, т.е. для всех объектов класса
    — привязка происходит в момент загрузки класса, не раньше («загружен, но не вызван») и не позже («выполнился коллбек-конструктор класса»)

    все относится как к переменным, так и методам объекта.

    однако, один вопрос в статье упущен (или мне показалось?): наследование статических методов и полей.
    1. можно ли вызывать такие методы из потомка?
    2. можно ли перекрывать такие методы, и как добраться до метода суперкласса?
    3. время жизни статических полей?
    4. доступны ли во время выполнения конструктора\деструктора?
    5. что, если выполним два одновременных запроса к пхп, увидим ли мы одинаковые значение статических полей, или разные?
    6. то же, что и 5¸только в разное время?
    7. что, если обращаемся к статическому методу по нуллевой ссыле? (типичный вопрос для джава-юниора)
    • +1
      1) да, через через self/static
      2) да, да, через parent
      3) = времени жизни скрипта
      4) да
      5) разные.
      6) разные.
      7) в таком смысле в PHP ссылок нет
      • 0
        почему 5 и 6 разные?
        • 0
          Потому что bolk не прав. Зависит от того, что значит «запроса к пхп». Изначально все зависит от реализации, может быть в статических полях константы — и мы всегда увидим одинаковые значения. Вероятно вопрос в том, сохраняются ли значения между разными запросами вида: запрос — php отработал — ответ, тогда нет, не сохранятся. А если php запущен, как демон, то сохранятся.
          Так что вопрос идиотский и ответ на него тоже не понятный.
          • +2
            Ответ на вопрос всегда даётся в общем случае. В общем случае там разные значения. Я примерно понимаю о чём спрашивает Lure_of_Chaos, потому что я не припомню больше языков в вебе, которые работали бы как ПХП — умирали между запросами. А у него вопрос явно относится к разделяемым между различными обработчиками значениям.

            Да, есть попытки привинчивания к PHP «честного» FastCGI или WSGI, но в данном случае постоянность значений не обеспечивается свойством статичных переменных, поэтому и тут мой ответ — «разные».
            • 0
              Я может глупость скажу, может чего-то не знаю. Но вроде Perl, Ruby, Python, PHP умирают между запросами, если они выполняются в обычном контексте веб-сервера.
              • 0
                Про Руби не знаю, а у Перла есть «честный» FastCGI, «Пайтон» же чаще всего пускают через WSGI.
          • 0
            что значит «в статических полях константы»?
        • 0
          Это будут разные поля, не одно и то же. А значение может быть какое угодно, хотите будет разное, хотите одинаковое.
      • 0
        2) — через имя класса, из которого хотите вытащить статический метод. parent:: работает только в контексте вызова метода объекта
  • 0
    однако, один вопрос в статье упущен (или мне показалось?)

    Ну всего в одну статью не впихнёшь, я бы хотел серию сделать с подзаголовком «Готовимся к собеседованию». Часть ваших вопросов интересна, часть — не имеет смысла в PHP )))
  • +4
    Ох как мне не нравятся подобные статьи, точнее их последствия. Мы один раз долго не могли понять почему серия из 5ти соискателей отвечает на одинаковый вопрос слово в слово. И вроде бы правильно отвечает, а если копнуть глубже 4 из 5 не смогли развить тему и чуть дальше. После поиска в гугле нашли подобную статью и ответ на наш вопрос в ней. Долго смеялись и просили на следующих собеседованиях отвечать другими терминами.

    P.S. Статья хорошая, не подумайте. Автору спасибо
    • 0
      А вы копайте, копайте глубже ))) Не копая не поймешь — цитирует собеседуемый статью, или действительно понимает смысл произносимых слов.
    • +2
      Значит вопрос скомпрометирован, надо генерировать новый.
    • +2
      А откуда бы вы хотели чтоб человек черпал информацию в том числе по static в php? Я думаю это не проблема конкретно этой статьи, а вообще образования, конечно кто-то просто зазубрит что-то, что от него требует, а кто-то прочитает официальный мануал, прочитает несколько таких статей, попробует что-то сделать сам и усвоит знания. И я думаю 1 из 5 не так уж плохо, вот серьёзно :)
      • 0
        Я согласен ) Вопрос лишь в том что 4 из 5 перед собеседованием вместо теории и мануалов читают мануал как пройти собеседование по PHP.
    • 0
      А вы на собеседованиях ставите условие, чтобы ответ был более-менее уникальным? Тогда уж лучше тестовое задание давать, вместо этой теории.
      • 0
        Нет просто если мы слышим что человек цитирует подобную статью мы просим перефразировать ответ. Задание к сожалению меньше выявляет проблем. Лучше комплекс.
  • +5
    Скажите, а вы в своем «обыденном» коде как часто используете статические локальные переменные?
    • 0
      Бывает использую в рекурсивных функциях, например, для обработки древовидных структур, когда нужна общая переменная в процессе обработки. Ее можено либо передавать как аргумент, либо сделать глобальной, либо статической. Мне больше нравится последнее.
      • 0
        Ну в принципе ее можно сделать членом класса еще :)
        • 0
          Конечно, я просто думал, что вы речь ведете только про static относительно функций, а не методов классов и объектов.
        • 0
          нельзя, если древовидная структура — это скомпонированное древовидное множество из одной иерархии класса, но в таком случае лучше проходить каким-то посетителем
    • +1
      Мы тоже не часто используем их, но есть места, где они спасают. Плохо только одно, когда их начинает писать тот, кто не понимает как они работают.
    • +1
      Не часто. Ровно также, как нечастно использую, скажем, ссылки. Или интерфейс ArrayAccess.
      Но это не значит, что я имею право не знать о такой возможности.
    • 0
      Вообще эта вещь очень удобна для кэширования результатов выполнение функции, поэтому раньше когда программировал функционально частенько применял, с переходом на ООП в методах применяю редко по причине описанной в статье — легко выстрелить в ногу.
  • +4
    Прошу прощения, не хочу показаться занудой, но зачем в коде:

    function foo() {
    static $a = 0;
    echo $a;
    $a = $a + 1;
    }

    echo foo(); // 0
    echo foo(); // 1
    echo foo(); // 2

    echo перед вызовом функции foo?
    • 0
      Можно написать и echo(foo()), просто echo (она же print) — языковая конструкция, а не функция.
      • –1
        Результат тот же, но echo — не print хотя бы по тому, что echo — конструкция языка, а print — функция, хоть внутри php source и имеют вызов одного функционала добавления строки в буффер вывода. Всё же они работают немного по-разному.
        Например: сделайте
        echo (echo "string");
        

        и
        echo (print "string");
        
        • 0
          print тоже языковая конструкция, а не функция.
          Отличия
          — print всегда вернет 1, а еcho ничего не возвращает.
          — print допускает только один параметр, а echo несколько через запятую
          • +1
            echo не просто не возвращает (функция, не возвращающяя значения в php при присвоении даст null), выражение вызывает fatal error при попытке присвоить результат echo.
    • +1
      Впрочем, Вы правы, туплю-с, foo() ничего же не возвращает.
    • +1
      Благодарю Вас, исправил.
  • 0
    В PHP переменные локальны. Это значит, что переменная, определенная и получившая значение внутри функции (метода), существует только во время выполнения этой функции (метода). При выходе из метода локальная переменная уничтожается, а при повторном входе — создается заново. В коде выше такой локальной переменной является переменная $a — она существует только внутри функции foo() и каждый раз при вызове этой функции создается заново

    В целом да, но не всегда :)
    НО, конкретно в том примере, что приведен выше — да
  • 0
    спасибо за статью!
  • +1
    И кстати, всё написанное выше относится только к свойствам. Использование статического свойства через "->" невозможно и ведет к фатальной ошибке.

    В первом предложении не должно быть «к методам» вместо «свойствам»?
    • 0
      Да. Исправил, спасибо!
  • +1
    Вот я мимо проходил, статью не читал, но может надо готовиться к программированию на PHP, а не к собеседованию?
    • 0
      В вопросах часто звучат нюансы, которые либо знаешь, потому что читал/сам ошибался и искал фикс/экспериментировал, либо нет, так как не приходилось использовать, и касается вопросов не только по PHP.
      • –1
        Абсолютно согласен, однако то что такие вопросы задают не значит что это хорошо/правильно. Сам на собеседования задавал такие вопросы, мне задавали их на собеседованиях. Когда подрос понял что это глупо. Но могу быть не прав, если у кого то есть веские аргументы в пользу такого подхода.
        • 0
          Когда подрос понял что это глупо

          Не подскажете — что глупого в вопросах на знание языка, задаваемых кандидату на позицию разработчика на этом языке?
          • +2
            Я говорю не о знании языка, а конкретно о глупых вопросах именно на собеседовании, как их назвали в комментарии выше — «нюансах». Конечно нужно знать язык, в этом суть, но очень часто спрашивают о ситуациях которые встречаются ну очень редко или вообще могу не встретится человеку. Понятно что их тоже хорошо бы знать и они могут пригодиться, но если человек знает хорошо свою работу и вообще способный, то когда встретится тот самый нюанс, я думаю, он сможет с ним справиться. На крайний случай, если нет, то для этого и нужна команда и вообще все люди/программисты продолжают дальше учиться, даже когда уже знают достаточно.

            Ещё раз повторю, статью я не читал, меня взволновал заголовок и в следствии чего последовал вопрос. На счёт «нюансов» отвечаю так как про них заговорили в ответе к моему комментарию. Если же статья не про нюансы, а про другое, тогда мой первый вопрос на счёт заголовка до сих пор в силе.
            • 0
              Если же статья не про нюансы, а про другое, тогда мой первый вопрос на счёт заголовка до сих пор в силе.

              Статья, с вашего позволения, не про «нюансы», к которым вы испытываете столь сложные чувства, а про систематизацию. Про собрать в одном месте всё, что касается одного ключевого слова языка и систематизировать эти знания.
              • +1
                Это здорово, но позвольте, вы так и не ответили тогда на вопрос «почему для собеседования?». Если это общие знания которые нужно знать любому разработчику что бы хорошо программировать на языке, почему не назвать статью «Изучаем <язык>: <тема статьи>»? Лично в моём понимании, если статья называется «для собеседования», то это значит что там говорится про то, что с очень маленькой вероятностью может пригодиться в реальной работе. Выглядит так, что контент этой статьи нужен будет людям только что бы пройти собеседование, а дальше могут забыть о нём и не пользоваться.

                > а про систематизацию. Про собрать в одном месте всё, что касается одного ключевого слова языка и систематизировать эти знания.

                Вы молодец что делаете это и к статье самой или к вам у меня претензий быть не может. Моё желание лишь понять, чем вы руководствовались когда называли это «для собеседования».
                • +1
                  Это здорово, но позвольте, вы так и не ответили тогда на вопрос «почему для собеседования?»

                  Извините, не увидел вопроса.

                  Потому что именно собеседование для многих заменяет экзамен на профессионализм. Рядовой разработчик на PHP зачастую только на собеседовании, к стыду своему, понимает, что он как тот Джон Сноу — имеет в портфолио десяток проектов, кучу фреймворков и паттернов, но ничего не знает…
        • 0
          Честно говоря, я и сам отношусь к подобным вопросам скорее негативно. Но это не отменяет того факта, что они просто есть.
  • 0
    Интересно, только я не знал первый вариант использования «static» (создание статической локальной переменной)? Наверное, минус постоянной ОО разработки — с некоторыми нюансами языка, проявляющимися при процедурном программировании, просто никогда не сталкиваешься.
    • +2
      Молодые многие не знают по опыту, это этакий олдскул.
      • –3
        А по-моему, это ненужная конструкция. Если тебе нужна волшебная константа, то лучше объявить её прямо в классе, чтобы она всегда на виду была, потому что это волшебная зависимость.
    • 0
      Некоторые вещи про php лучше не знать. Например то что есть трюк вызывать protected методы не только из вашего класса )
      • 0
        Имеется ввиду из классов, не наследующих данный? Если так, то заинтриговали :) Поделитесь ссылкой?
        • 0
          Если мне не изменяет память то достаточно что бы у классов был общий родитель. Но не обязательно наследовать нужный класс.
        • +1
          Я думаю fear86 говорит о следующем кейсе
          код
          <?php
          
          class firstClass
          {
              /** @var string */
              protected $message;
          
              public function __construct($message)
              {
                  $this->message = $message;
              }
          }
          
          class secondClass extends firstClass
          {
              /** @var firstClass */
              protected $firstClass;
          
              public function __construct(firstClass $firstClass)
              {
                  $this->firstClass = $firstClass;
              }
          
              public function accessProtected()
              {
                  return $this->firstClass->message;
              }
          }
          
          $a = new firstClass('Hello protected');
          $b = new secondClass($a);
          
          var_dump($b->accessProtected());
          
          

          • 0
            Да, я имел ввиду вызов из других обьектов. И я ошибся с общим родителем, класс надо наследовать, или хотя бы наследовать тот класс в иерархии, который содержит нужный нам метод/свойство.
            Вот так тоже можно:
            class a {
              protected function test()
              {
                return 'protected';
              }
            }
            
            class e extends a {
            }
            
            class c extends a {
              public function __call($name, $args)
              {
                return call_user_func_array(array(array_shift($args), $name), $args);
              }
            }
            
            $e = new e();
            $c = new c();
            echo $c->test($e);
            
          • 0
            Забавная «фича». Век живи — век учись.
      • 0
        Тоже интересно, может все таки имелось ввиду вызывать не только из вашего объекта — php.net/manual/ru/language.oop5.visibility.php#language.oop5.visibility-other-objects, рефлекшены уж наверное тут не подразумевались.
  • 0
    Ну скажите как интересно, описать что означает static в типовом ООП, причём так, будто какие-то неожиданные свойства открылись. А реально неожиданное — это только «позднее связывание» с заменой $self на static. Правда практическое применение придумать что-то не выходит у меня.

    Автору спасибо — «размял» немного мозг, но лучше было бы написать, что такое static и почему от него ожидают именно того поведения, которое приведено в статье.
    • 0
      P.S. На всякий случай: ключевое слово статик вовсе не связано с «Значение помеченной таким образом переменной сохраняется после окончания работы функции» — это следствие.
    • +1
      А реально неожиданное — это только «позднее связывание» с заменой $self на static.

      Эта возможность появилась лет пять назад, в 5.3. Она является основной многих современных фреймворков, например, можно сказать что Yii 2 обязан своему появлению переходу именно на 5.3 А для вас это вдруг неожиданность.

      Поэтому я и пишу такие статьи. Чтобы «неожиданностей» в мануале по языку, за знание которого вам платят деньги, было поменьше.
      • 0
        «Неожиданное» в смысле «классических» ООП языков. Ну никак из смысла static не вытекает возможность сделать ссылку на класс-потомок сделать доступной в родительском классе. Обычно просто используются виртуальные методы и т.п.
        • 0
          Скорее просто неудачный выбор ключевого слова.
          Согласитесь, что например children::method() или current::method() было бы гораздо проще запоминать и объяснять начинающим, нежели static::method()
          • 0
            именно static и ведет себя так, как должен вести себя в классических ОО-языках, для меня было большей неожиданностью поведение self когда я узнал о позднем связывании. потому следует понимать когда нужно использовать self, а когда static. как по мне, то использование static более прозрачно, а вот self использовать уже когда это дейсвительно нужно оправдано
    • 0
      new static(); самое частое использование
  • 0
    Странно, столько мнений, но никто не сказал, что не стоит увлекаться статикой. В любой книге про ООП написано, что она портит архитектуру — делает код нетестируемым и ломким, а классы тесно связаными друг с другом. Мне кажется именно об этом стоит говорить на собеседовании.
    • +1
      Дело в том, что это мнение про «не стоит увлекаться» само по себе ничего не значит, если вы не способны это мнение обосновать.

      Что такое «не стоит увлекаться»? Почему? Только потому, что «в любой книге написано»? В чём проблема тестирования такого кода? Как эти проблемы решать?

      Видите, сколько сразу вопросов, которые вам зададут на приличном собеседовании?

      P.S. Мнение «статика — всегда плохо» как минимум спорно. Есть ORM где, например, статические методы класса сущности работают с таблицей сущностей, динамические — с конкретной записью в этой таблице. Это тоже плохо? Почему?
      • 0
        Статика, глобальные переменные это кошмар при написании unit тестов.
        Тесты должны исполняться независимо друг от друга.
        Чтобы быть уверенным, что никто до вас не вызывал функцию foo, вам придется перезапускать php процесс перед выполнением каждого теста.
        function foo() {
          static $a = 0;
          echo $a;
          $a = $a + 1;
        }
        
        foo(); // 0
        foo(); // 1
        foo(); // 2
        
        • 0
          Во-первых вы немного путаете. Предыдущий юзер имел в виду, под «статикой» статические методы классов все-таки.
          Во-вторых да, тесты должны выполняться независимо. Но с другой стороны архитектура может потребовать от вас некую «функцию с внутренним состоянием», чем бы это ни было, пусть даже это будет объект, который банально считает число вызовов своего определенного метода. И как быть? Как бы вы решили эту дилемму?
          • 0
            Ну, объект — он и хранит состояние, не ф-я.

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