PHP Static Methods
What Is a Static Method?
In simple terms: A static method belongs to the class itself, not to any particular object. You call it directly on the class name, without creating an object first: Str::slug('Hello World'). It is useful for operations that do not need any object's data — like converting text or creating objects in different ways.
Technically: A method declared with the static keyword is called with the scope resolution operator: ClassName::method(). Inside a static method there is no $this; it can access only its parameters, static properties, constants, and other static methods (through self:: or static::). Static methods can still create and return objects.
Instance Methods vs Static Methods
| Instance Method | Static Method | |
|---|---|---|
| Declared as | public function total() | public static function fromArray() |
| Called as | $cart->total() | Money::fromRupees(10) |
| Needs an object | Yes | No |
$this available | Yes | No |
| Typical use | Behavior using the object's state | Factories, pure helpers, class-level operations |
Defining and Calling Static Methods
<?php
final class Str
{
public static function slug(string $text): string
{
return strtolower(trim(preg_replace('/[^A-Za-z0-9]+/', '-', $text), '-'));
}
public static function limit(string $text, int $length, string $end = '...'): string
{
if (mb_strlen($text) <= $length) {
return $text;
}
return rtrim(mb_substr($text, 0, $length)) . $end;
}
public static function headline(string $text): string
{
return self::limit(ucwords(strtolower($text)), 25);
}
}
echo Str::slug('Learn PHP OOP!') . "\n";
echo Str::limit('Learn PHP object-oriented programming', 20) . "\n";
echo Str::headline('LEARN PHP OBJECT-ORIENTED PROGRAMMING') . "\n";
print_r(array_map(Str::slug(...), ['Desk Lamp', 'Gel Pen (Blue)']));
Output
learn-php-oop
Learn PHP object-ori...
Learn Php Object-oriented...
Array
(
[0] => desk-lamp
[1] => gel-pen-blue
)
How It Works
Str::slug(...)is called on the class; nonew Str()is needed.- Inside the class, one static method calls another with
self::limit(...). - These methods depend only on their parameters — they are pure functions grouped in a class.
Str::slug(...)(first-class callable syntax) turns the static method into a callback forarray_map(); the older forms[Str::class, 'slug']and'Str::slug'also work.
Note how ucwords() produced Php and Object-oriented: it capitalizes only after spaces by default, and it does not know about acronyms. Static helpers are only as smart as their implementation.
Named Constructors
The most valuable use of static methods in OOP is creating objects in clearly named ways (see PHP Constructor):
<?php
final class Temperature
{
private function __construct(private float $celsius) {}
public static function fromCelsius(float $celsius): self
{
return new self($celsius);
}
public static function fromFahrenheit(float $fahrenheit): self
{
return new self(($fahrenheit - 32) * 5 / 9);
}
public function celsius(): float
{
return round($this->celsius, 1);
}
}
echo Temperature::fromFahrenheit(98.6)->celsius() . " °C\n";
echo Temperature::fromCelsius(36.6)->celsius() . " °C\n";
Output
37 °C
36.6 °C
The static methods have full access to the class's private constructor, while outside code cannot call it. The names make it impossible to confuse Celsius and Fahrenheit input.
$this Is Not Available
<?php
class Counter
{
private int $count = 0;
public static function reset(): void
{
$this->count = 0;
}
}
try {
Counter::reset();
} catch (Error $e) {
echo $e->getMessage() . "\n";
}
Output
Using $this when not in object context
A static method is not called on an object, so there is no object whose count could be reset. Methods that work with an object's state must be instance methods.
Calling Instance Methods Statically
The reverse is also an error:
<?php
class Cart
{
public function total(): float
{
return 0.0;
}
}
try {
Cart::total();
} catch (Error $e) {
echo $e->getMessage() . "\n";
}
Output
Non-static method Cart::total() cannot be called statically
Calling Static Methods on Objects
Static methods can also be called through an object ($str::slug('x') or $object->staticMethod()), but this hides the fact that no object state is used. Prefer ClassName::method().
self:: vs static::
Inside a class, static methods are called with self:: or static:::
self::method()calls the method of the class where the code is written.static::method()calls the method of the class that was actually called, which matters when a child class overrides the static method.
This difference, called late static binding, is explained in Late Static Binding.
When Static Methods Are a Good Choice
| Good Use | Example |
|---|---|
| Named constructors / factories | Money::fromPaise(500), User::fromArray($row) |
| Pure helper functions grouped by topic | Str::slug(), Arr::pluck() |
| Operations on the class as a whole | Order::statuses() returning all valid statuses |
| Enum-like lookups | PaymentMethod::fromCode('upi') |
When to Avoid Them
| Problem | Why |
|---|---|
| Hidden dependencies | Mailer::send() called deep inside a class cannot be replaced in tests |
| Global state | Static methods that change static properties behave like global variables |
| Inflexibility | Static calls cannot be swapped for another implementation via interfaces |
// Hard to test: a fixed, static dependency
final class OrderService
{
public function place(array $order): void
{
Mailer::send($order['email'], 'Order placed');
}
}
// Flexible: the dependency is injected and can be replaced
final class OrderService
{
public function __construct(private MailerInterface $mailer) {}
public function place(array $order): void
{
$this->mailer->send($order['email'], 'Order placed');
}
}
Static methods are ideal for code with no side effects and no dependencies. Anything that talks to databases, files, networks, or the clock is better provided as an injected object.
Note: Laravel "facades" (
Cache::get(),Mail::send()) look like static calls but forward to objects resolved from a service container, which is how they remain replaceable in tests.
Practical Example: Building Objects From Database Rows
<?php
final class Customer
{
public function __construct(
public readonly int $id,
public readonly string $name,
public readonly string $email,
public readonly DateTimeImmutable $joinedAt,
) {}
public static function fromRow(array $row): self
{
return new self(
(int) $row['id'],
$row['name'],
strtolower($row['email']),
new DateTimeImmutable($row['joined_at']),
);
}
public static function fromRows(array $rows): array
{
return array_map(self::fromRow(...), $rows);
}
}
$rows = [
['id' => '7', 'name' => 'Asha', 'email' => 'Asha@Example.com', 'joined_at' => '2026-01-12 09:30:00'],
['id' => '9', 'name' => 'Bala', 'email' => 'bala@example.com', 'joined_at' => '2026-03-05 18:10:00'],
];
foreach (Customer::fromRows($rows) as $customer) {
printf("#%d %s <%s> joined %s\n", $customer->id, $customer->name, $customer->email, $customer->joinedAt->format('M Y'));
}
Output
#7 Asha <asha@example.com> joined Jan 2026
#9 Bala <bala@example.com> joined Mar 2026
Step-by-Step Explanation
- Database drivers return rows as arrays of strings.
fromRow()converts one row into a properly typedCustomer: the ID becomes anint, the email is normalized, and the date becomes aDateTimeImmutable. fromRows()maps every row withself::fromRow(...).- The conversion logic lives in the class it belongs to, and every part of the application creates customers from rows the same way.
Common Mistakes
Using $this in Static Methods
Effect: Error: Using $this when not in object context.
Fix: Pass the needed data as parameters, or make the method non-static.
Calling Instance Methods Statically
Effect: Error: Non-static method ... cannot be called statically.
Fix: Create an object and call the method on it.
Static Methods With Side Effects Everywhere
Effect: Hidden dependencies, global state, and untestable code.
Fix: Inject services as objects; keep static methods pure.
"Utility" Classes Collecting Unrelated Functions
Effect: A Helpers class with dozens of unrelated methods.
Fix: Group helpers by topic (Str, Arr, Money), or use namespaced functions.
Best Practices
- Use static methods for named constructors and pure, dependency-free helpers.
- Keep side effects (database, files, network, time) in injected objects, not static calls.
- Call static methods with
ClassName::method(), and usestatic::when subclasses may override them. - Use first-class callable syntax (
ClassName::method(...)) to pass static methods as callbacks. - Avoid static methods that read or change static state unless that state is intentional and well-contained.
Official reference: https://www.php.net/manual/en/language.oop5.static.php