Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

garrettmassey's avatar

How does Laravel allow us to use both static and non static versions of methods on a class?

I’ve worked with PHP and Laravel for a while now, but something just occurred to me that I don’t know the answer to:

How does Laravel allow for a class to have static calls and non static calls to a method with the same name? For example:


use App\Models\User;

$users = User::where(‘status’, ‘=‘, ‘active’)->where(‘type’, ‘=‘, ‘subscriber’)->get();

It never occurred to me to look into this, and now I’m curious as to how it works. I’d look in the code base but I’m on a train just using my phone and don’t have my laptop 😂

0 likes
2 replies
LaryAI's avatar

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 that where is not a static method on User.
  • The __callStatic method is triggered.
  • It creates a new instance of the model (new static) and calls the non-static where method 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.

Please or to participate in this conversation.