skip to content

In PHP, what does a static local variable inside a function do, how long does it live, and what changed in PHP 8.1 and 8.3?

level: middleimportance: should knowfreq 42%

answer

  1. initialised once, kept between calls
  2. lives for the request, not forever
  3. 8.3: any expression as initialiser
  4. 8.1: inherited methods share it
  5. one per closure object

basics

~20 s

A static local keeps its value between calls, and its initialiser runs only on the first call; it lives until the request ends. PHP 8.3 allows any expression as initialiser; since 8.1 inherited methods share it with the parent.

solid answer

~50 s

`static $cache = [];` declares a variable that is **local to the function** but **not reset** when the call returns: the initialiser runs once, and later calls see the last value. A common use is memoising work inside a helper, such as loading a weather station's settings file once. It lives until the **end of the current request**: under the usual share-nothing model it starts fresh on the next request, so it is not a cross-request cache. **PHP 8.3** allowed arbitrary initialisers such as `static $cfg = loadConfig();`; before, only constant expressions were allowed. **PHP 8.1** made an inherited, non-overridden method **share** its static variables with the parent method, like a static property. Statics in a method are shared by **all instances** of the class, and a closure's statics belong to that closure object, so recreating the closure resets them.

code

php · 14 lines
php
<?php
class Sensor
{
    public static function reads(): int
    {
        static $count = 0;
        return ++$count;
    }
}
class WindSensor extends Sensor {}

var_dump(Sensor::reads());      // int(1)
var_dump(Sensor::reads());      // int(2)
var_dump(WindSensor::reads());  // int(3) since PHP 8.1, int(1) before

go deeper

for a junior

Recall that a static local keeps its value between calls of the same function and starts from its initialiser on the first call.

for a middle

Explain its per-request lifetime, the 8.3 arbitrary-initialiser change and the 8.1 sharing between parent and inherited methods.

for a senior

Spot static memos that leak state between tests or grow without bound in long-running processes, and replace them with injected caches.

for a principal

Decide where memoisation belongs, request-scoped statics, shared caches or explicit services, as the codebase moves toward long-running workers.

## What static does in a function A normal local variable is created on each call and destroyed when the call returns. A **static** local variable is declared with the `static` keyword and keeps its value between calls: ```php <?php declare(strict_types=1); function stationConfig(): array { static $config = null; // initialised on the first call only if ($config === null) { $config = require __DIR__ . '/station.php'; } return $config; } ``` The variable is still **local**: no other function can see it by name. What changes is its lifetime. The manual's examples show a counter that would print `0` forever without `static` and counts up with it, and a recursive function that uses a static counter to stop. ## How long it lives A static variable lives in the process that runs the script, for the **current request**: - Under PHP's usual request model, all script state, statics included, is torn down at the end of each request. The next request calls `stationConfig()` and loads the file again. - It is therefore a **per-request memo**, not a cache shared between requests or between worker processes. Keeping data across requests needs a real cache. - In a long-running CLI script or a worker runtime that keeps the application in memory, the same static lives as long as the process, which can turn a harmless memo into stale data or unbounded memory growth. Worker runtimes are their own topic. ## Initialisers: the PHP 8.3 change | Version | Allowed initialiser | |---|---| | before 8.3 | constant expressions only: `static $n = 0;`, `static $n = 1 + 2;` | | 8.3 and later | arbitrary expressions: `static $cfg = loadConfig();`, `static $n = sqrt(121);` | Whatever the form, the initialiser is evaluated **once**, on the first call that reaches the declaration. ## Methods, inheritance and instances In a method, a static variable belongs to the **method**, not to an object: 1. **Shared by all instances.** Two objects of the same class calling the method see the same static. A per-object cache must be a property instead. 2. **Inherited methods share since PHP 8.1.** When a child class inherits a method without overriding it, both classes now use the **same** static variable. The manual's example: `A::counter()` twice gives 1 and 2, then `B::counter()` gives 3 and 4; before 8.1 it restarted at 1. The manual summarises that static variables in methods now behave like static properties. 3. **Overridden methods have their own**, because they are different methods. ## Closures A static variable inside an anonymous function belongs to that **closure object**. If the closure is created anew on every call of the surrounding function, its static starts over each time. Keep the closure in a variable or property if its state should persist. ## Traps - **References are not stored statically.** Assigning a reference to a static variable (`$obj = &$new;`) is not remembered on the next call; the manual shows the static reading `NULL` again. Assign by value instead. - **Hidden state in tests.** A static memo survives between test methods in one PHP process, so one test can see data loaded by another. Provide a way to reset it, or prefer an injected cache object. - **Unbounded growth.** A static array used as a memo keyed by input grows with every distinct input for the life of the process. ## Summary Static locals are a small, useful tool for per-request memoisation and counters. Know their lifetime, the 8.3 initialiser change, the 8.1 inheritance change and that they are shared across instances, and they will not surprise you.

  • Is a static local a good way to cache data between HTTP requests?
    No. Under PHP's usual request model everything, statics included, is torn down at the end of each request, and each worker process has its own memory anyway. A static is a per-request memo. Data that must survive requests belongs in a real cache, a database or a file.
  • Two instances of the same class call a method with a static variable; do they each get their own?
    No. The static belongs to the method, not the object, so all instances share one value, like a static property. Since PHP 8.1 a child class that inherits the method without overriding it shares the value too. Use an instance property for per-object state.

A static local is like a notepad chained to one desk: whoever sits there sees the last note, nobody at another desk can read it, and the cleaners clear it at closing time each night, which is the end of the request.

saying these in an interview costs you the question

  • A static local keeps its value between HTTP requests under PHP-FPM.
  • Each object gets its own copy of a static variable declared in a method.
  • Static variables can be initialised only with literals, even in PHP 8.5.
  • A child class always gets its own copy of an inherited method's static variable.
  • A static variable is visible to other functions in the same file.