Normal properties and methods belong to an object. Static ones belong to the class itself. You use them with :: and no new.
<?php
class MathHelper
{
public static function square(int $n): int
{
return $n * $n;
}
}
echo MathHelper::square(7);
49
Static properties
A static property is shared by all objects of the class. There is only one copy.
<?php
class Visitor
{
public static int $count = 0;
public function __construct()
{
self::$count++;
}
}
new Visitor();
new Visitor();
new Visitor();
echo Visitor::$count;
3
Inside the class, write self::$count. From outside, write Visitor::$count.
No $this in static methods
A static method is not tied to an object, so $this does not exist there. It can use only static properties, other static methods and constants.
<?php
class Config
{
private static array $values = [];
public static function set(string $key, string $value): void
{
self::$values[$key] = $value;
}
public static function get(string $key, string $default = ""): string
{
return self::$values[$key] ?? $default;
}
}
Config::set("site", "Code Corner");
echo Config::get("site") . "\n";
echo Config::get("missing", "n/a");
Code Corner
n/a
self vs static
self:: always means the class where the code is written. static:: means the class that was actually called (late static binding). It matters with inheritance.
<?php
class Model
{
public static function create(): static
{
return new static();
}
public static function name(): string
{
return static::class;
}
}
class User extends Model {}
echo User::name() . "\n";
echo get_class(User::create());
User
User
If create() used new self(), it would build a Model, not a User.
Static factory methods
A static method is a good place for a named constructor.
<?php
class Temperature
{
private function __construct(public readonly float $celsius) {}
public static function fromFahrenheit(float $f): self
{
return new self(($f - 32) / 1.8);
}
}
echo round(Temperature::fromFahrenheit(212)->celsius);
100
When to avoid statics
- A static property is global state. Any code can change it, so bugs are hard to find.
- Static methods are hard to replace in tests.
- A class full of static methods is just a bag of functions with a name.
Utility functions (MathHelper::square) and factory methods are fine. For services that hold state (a database connection, a logger), use normal objects and pass them in. See Dependency Injection.
Not the same as static variables
static $x inside a function (see Static Variables) keeps a value between calls. Same keyword, different feature.