Reputation: 14931
when reading here you will see facades are not really facades
why does laravel's facade behave like a singleton?
all the methods on Facades are static anyway (go look yourself in Illuminate\Support\Facades
)
and some aliases actually are just that, normal classes for example
'Arr' => Illuminate\Support\Arr::class,
whats the point of it being facades?
Upvotes: 3
Views: 1555
Reputation: 13467
Why is laravel mainly using Facades instead of singletons?
Facades ARE singletons because of the way they're implemented.
First, let's define some of the terms we're using:
Facade
can refer to two things:
Singleton
is a creational design pattern that lets you ensure that a class has only one instance, while providing a global access point to this instance. (Source)
These definitions are not mutually exclusive. Something can be a facade and a singleton (whether or not they should be both is a different conversation).
Laravel's Facades are singletons in two ways: the abstract Facade class, and Laravel's IoC Container.
The abstract Facade
class - the parent of all individual Facades - is the primary reason Facades act as singletons. When a Facade is called, it resolves its underlying class from Laravel's container and saves it to a local static property. Subsequent calls will refer to the local property value, rather than resolving from the container again.
Laravel's Inversion of Control Container is another way that a Facade can reference a singleton object. When you bind a service to the container, you can use Container::singleton()
to ensure that a service always resolves to the same instance when retrieved.
I hope that clarifies that something can be a singleton and a facade simultaneously.
and some aliases actually are just that, normal classes for example
An alias in this context is just a call to PHP's class_alias()
, and is a way of making Facades and other classes easier to use by minimizing the fully-qualified class name (namespace + class name). Rather than needing to use Illuminate\Support\Arr;
, you can just use Arr;
or \Arr::get()
in your code without the import. This is particularly useful within Blade templates. These aliases are useful for but not limited to Facades.
if all functions are static, why are the helper functions like
session()
all working with->
e.g.config()->set()
vs config()::set()when the facade does
Config::set()`?
Just a difference in purpose and implementation. A Facade is a proxy - all interaction happens with the Facade itself, but it proxies requests to the underlying service. The helper functions don't proxy any calls, they only return the service retrieved from the container.
// Only interacts with the Facade class.
// set() is proxied via the magic __callStatic() method.
Config::set();
// config() returns an instance of the Config Repository class.
// Subsequent calls are directly on that instance.
// No magic methods used.
config()->set();
Facades also come with some mocking and testing utilities that may make them a better solution, depending on your testing needs.
Upvotes: 7