PHP Static Methods and Static Properties

Use class-level operations deliberately and recognize shared mutable state, inheritance and testing trade-offs.

Lesson 48 of 86Advanced10 min read

A static method belongs to a class rather than one particular object instance. You call it with ClassName::method(). A static property also belongs to class-level storage and can be shared by instances that use that declaration. These features are useful for some factories and small class-owned operations, but mutable static state can create hidden dependencies.

This guide separates static operations from instance behavior, explains the absence of $this, and traces a small counter. It also covers inheritance and runtime lifetime so a demonstration counter is not mistaken for persistent storage or a concurrency-safe system.

Static methods have no current instance

Declare a method with static when it does not need an individual object's state. Inside a static method, $this is unavailable because no current instance is supplied. The method can use its parameters, local variables, class constants and accessible static members. It can also create objects and return them.

A named factory can be a useful static method: Money::fromCents(250) makes the construction intent clear. A pure conversion utility can also fit. However, putting a method in a class and marking it static does not automatically create good design. A namespaced function may be sufficient for a general calculation without class ownership.

Use an instance method when behavior depends on injected services or object state. An email sender that needs a transport, logger and configuration is easier to vary and test as an object with those dependencies than as a static method reading global configuration. Choose the ownership model from the dependencies.

Static properties hold class-level mutable state

Declare a property with static and access it as self::$count inside the class or ClassName::$count when public access is permitted. The dollar sign distinguishes a static property from a class constant. Unlike a constant, a normal static property can be reassigned.

Visibility still applies. A private counter can be updated through public methods without exposing arbitrary assignment. That improves encapsulation, but it does not remove shared state. Two callers using the same class storage can still influence one another. Tests may need reset mechanisms, which is often a signal that an injected stateful service would be cleaner.

Static state lives in memory according to the execution model. In a typical short web request it does not become a durable database. In a long-running worker it may survive across jobs in the same process. Neither model creates automatic sharing between processes or servers. Document the intended lifetime before using a static cache or registry.

self, static and inheritance

Self refers to the class where the method is declared. Static uses late static binding and can respect the called child class. That difference affects factories, constants and static members. A factory using new self creates the declaring class; one intentionally using new static can create the called subclass, subject to constructor compatibility.

Inherited static properties can share storage when the declaration is inherited. A child that redeclares a static property can create a different storage relationship. Do not assume every subclass automatically receives an isolated counter. Trace the actual declarations and test the intended behavior if shared state is essential.

Late binding should be an intentional extension policy. If a base factory assumes one constructor signature, a child with incompatible required arguments can break new static. Use an explicit factory interface or composed creator when construction varies significantly. A shorter class call should not hide an unstable inheritance contract.

Testing and dependency design

Static pure functions are straightforward to test because outputs depend only on explicit inputs. Mutable static registries are harder because results depend on previous calls and initialization order. Keep pure operations free from hidden global lookups, environment reads and clock access when those can be supplied as parameters.

Do not create a global service locator solely because static access is convenient. Callers then conceal their dependencies behind class names, making it harder to provide test implementations or understand startup requirements. An injected interface lets callers state what service they need and lets the application decide which implementation to provide.

The PHP static keyword reference explains the language rules. Modern PHP rejects calling nonstatic methods statically; old tutorials showing that style should be updated. A method that needs instance state requires an actual object, not a static-looking shortcut.

PHP Static Methods and Static Properties Examples

Each example shows the code, the output it produces and what each part does.

Example 1

A static factory returns an instance

The factory does not use $this; it constructs a new object. The amount method does use the resulting object's state. A production money type would also define currency, bounds and arithmetic rules, but the example isolates the static-versus-instance distinction.

PHP
<?php
class Money {
    private function __construct(private int $cents) {}

    public static function fromCents(int $cents): self {
        return new self($cents);
    }

    public function amount(): int {
        return $this->cents;
    }
}
echo Money::fromCents(250)->amount() . PHP_EOL;
Output
250
Example 2

Count creations within one execution

Both calls update the same class property. This is not a safe distributed identifier generator. Another process starts with its own storage, and a restart loses the count. Use a database identity or a deliberate identifier service when uniqueness must persist across requests.

PHP
<?php
class LocalCounter {
    private static int $count = 0;

    public static function next(): int {
        return ++self::$count;
    }
}
echo LocalCounter::next() . PHP_EOL;
echo LocalCounter::next() . PHP_EOL;
Output
1
2

PHP Static Methods and Static Properties in Real Projects

Practical task: normalize a stable product code

Create a class-owned pure normalization method that trims a supplied code and converts its ASCII letters to uppercase. It should not read requests, environment variables or shared counters. Then call it twice with different inputs. This demonstrates a static operation whose dependencies are entirely explicit.

PHP
<?php
class ProductCodes {
    public static function normalize(string $code): string {
        $normalized = strtoupper(trim($code));
        if ($normalized === '') {
            throw new InvalidArgumentException('Code is required');
        }
        return $normalized;
    }
}
echo ProductCodes::normalize(' p-101 ') . PHP_EOL;
echo ProductCodes::normalize('b-7') . PHP_EOL;
Output
P-101
B-7

The same input always receives the same result, aside from the documented invalid-input exception. For international identifiers, define the permitted alphabet and normalization rules rather than assuming ASCII uppercase is sufficient. If normalization starts requiring a configurable catalog service, reconsider whether an instance with an injected dependency would better express the new contract.

PHP Static Methods and Static Properties FAQ

Can a static method use $this?

No. It has no current object instance. Use parameters or construct an object when needed.

Is static a performance optimization?

It is primarily an ownership and calling model. Choose it for a clear contract rather than a presumed speed advantage.

Are static properties permanent?

No. They are process memory, not durable storage. Their practical lifetime depends on how PHP is executed.

Should a constant be a static property?

If the value must remain fixed, use a constant. Static properties are appropriate only when mutation is intended.

Why are my tests influencing each other?

Shared mutable static state may persist between test cases. Prefer explicit state ownership or reset it deliberately when the design requires it.

PHP Static Methods and Static Properties Exercises

Answer each one and check it instantly. If you get stuck, open the hint before the answer.

Multiple choiceeasy

A sender needs an interchangeable transport and logger. Which design usually makes those dependencies clearest?

PHP Static Methods and Static Properties Quiz

2 questions to check what you learned.

  1. Which variable is unavailable in a static method because there is no current instance?

    • A declared parameter
    • A local variable
    • $this
  2. What does a static property provide?

    • Class-level storage with a runtime-dependent lifetime
    • Automatic database persistence
    • Guaranteed uniqueness across servers