Great question! Laravel achieves this "magic" primarily through the use of PHP's magic methods and the Eloquent ORM's design pattern called the "static proxy" (or "static facade") pattern.
How It Works
1. Static Calls via __callStatic
When you call a method statically (e.g., User::where()), Laravel's Eloquent model doesn't actually define all these methods as static. Instead, it uses PHP's __callStatic magic method to intercept static method calls that don't exist.
Here's a simplified version of how this works in the Illuminate\Database\Eloquent\Model class:
public static function __callStatic($method, $parameters)
{
return (new static)->$method(...$parameters);
}
- When you call
User::where('status', '=', 'active'), PHP sees thatwhereis not a static method onUser. - The
__callStaticmethod is triggered. - It creates a new instance of the model (
new static) and calls the non-staticwheremethod on that instance.
2. Non-static Calls via __call
When you chain methods like ->where()->get(), those are regular instance methods. If a method isn't found, Eloquent also uses the __call magic method to forward calls to the underlying query builder:
public function __call($method, $parameters)
{
return $this->newQuery()->$method(...$parameters);
}
3. Fluent Query Building
- The static call (
User::where()) returns an Eloquent query builder instance. - You can then chain more methods (
->where()->get()) as usual.
Summary
- Static method calls (like
User::where()) are handled by__callStatic, which creates an instance and calls the method. - Instance method calls (like
$user->where()) are handled by__call, which forwards the call to the query builder. - This allows you to use both static and non-static versions of methods seamlessly.
Example
use App\Models\User;
// Static call (handled by __callStatic)
$users = User::where('status', '=', 'active')->where('type', '=', 'subscriber')->get();
// Non-static call (handled by __call)
$user = new User;
$users = $user->where('status', '=', 'active')->get();
Both work because of the magic methods in the Eloquent model!
If you want to dig deeper, check out the __call and __callStatic methods in the Illuminate\Database\Eloquent\Model class in the Laravel source code.