Laravel makes very liberal use of magic methods. When you do something like Artisan::command(), there is no actual public static function command() definition. So php instead looks to see if a __callStatic() method is defined, as a catchall for undefined methods. So somewhere in the Artisan Facade, you're likely to find something to the effect of:
public static function __callStatic($name, array $args = [])
{
$newObj = new static();
if (method_exists($newObj, $name)) {
return $newObj->$name(...$args);
}
}
Another tricky thing here is, more than likely the object you get back is not freshly instantiated as in the above example. Most of these follow the Singleton Pattern, meaning not only are you calling a non-static method statically, but you're calling it against the same instance of the target object every time.
$newObj = new static();
Would look more like
self::$preexistingObject = self::$preexistingObject ?: new static();
$newObj = self::$preexistingObject;
Most of this magic happens when the ServiceProviders 'boot' up. Somewhere in a configuration file, Laravel has been told what root class to associate with that "Artisan" Facade. It creates a new instance of that class, and holds on to it, reusing it, for the duration of that session.
Finally, to more directly answer your question and elaborate on Iainn's answer, this blew my mind the first time I discovered it, but native Php actually supports changing which object $this actually refers to within your anonymous function. You just call $closure->bindTo($newObject), as if the Closure is itself and object and bindTo() is a method. (For all I know, under the hood, Php might not actually make much of a distinction.)
You can do some cool stuff with this too. You could set your class up to receive a Closure, re-bind it to its own scope instead of that of the caller, retain it in a static associative-array, and access it later via. the Magic __call() method. The result is basically method-overloading; an opportunity to inject custom algorithms into a helper-class for use later in a declarative context.
Laravel provides a tool that can do just that. Macros, a Trait that you can plug into whatever you like. And it already has it baked into some toolsets that are known candidates for expansion, such as Collections, Eloquent\Builder, and Responses.