Reading — step 1 of 6
Learn
Magic methods are special method names PHP calls automatically in certain situations. They power the dynamic feel of PHP frameworks.
The lifecycle pair
class User {
public function __construct(public string $name) {}
public function __destruct() {
// called when last reference goes out of scope
echo "$this->name destroyed\n";
}
}
Property interception: __get, __set, __isset, __unset
Called when you access a property that DOESN'T EXIST (or isn't accessible):
class Config {
private array $data = [];
public function __get(string $name): mixed {
return $this->data[$name] ?? null;
}
public function __set(string $name, mixed $value): void {
$this->data[$name] = $value;
}
public function __isset(string $name): bool {
return isset($this->data[$name]);
}
}
$c = new Config();
$c->theme = 'dark'; // __set called
echo $c->theme; // __get called
isset($c->theme); // __isset called
Common trap: __get is also called when accessing a private property from outside.
Dynamic methods: __call, __callStatic
Called when an undefined method is invoked:
class Mock {
public function __call(string $name, array $args): mixed {
echo "called $name with " . count($args) . " args\n";
return null;
}
}
(new Mock())->whatever(1, 2, 3); // called whatever with 3 args
Used by mock objects, query builders, ORM proxies — $user->where('id', 1)->first().
Callable as function: __invoke
Makes an object behave like a function:
class Adder {
public function __construct(private int $by) {}
public function __invoke(int $n): int {
return $n + $this->by;
}
}
$add5 = new Adder(5);
echo $add5(10); // 15 — like calling a function
is_callable($add5); // true
Great for closures-with-state, dependency-injectable callables.
String coercion: __toString
class Money {
public function __construct(public int $cents) {}
public function __toString(): string {
return '$' . number_format($this->cents / 100, 2);
}
}
echo new Money(12345); // $123.45 — implicit string conversion
MUST return a string. Throwing from __toString was a fatal error pre-PHP 7.4.
Serialization: __sleep, __wakeup, __serialize, __unserialize
Called by serialize() and unserialize(). Useful for connection objects you can't store.
Common mistakes
- Overusing __get/__set — kills IDE autocomplete and static analysis.
- __call when a real method would do — confusing for callers reading the source.
- Forgetting that __get is bypassed for defined properties — defining a property at runtime via __set then reading $obj->name later might re-trigger __get if the property wasn't actually stored.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…