Several months ago in a blog post I saw people complaining about Laravel3’s Static methods stating Static methods are very difficult to Unit Test with and Laravel is a pile of Static API’s rather than a framework. I dont remember the Link. It said Laravel 3 is not architecturally “pure”, but it has super clean syntax.
But Laravel 4 combines both of those things. It’s extremely architecturally pure, yet maintains the same terse, expressive syntax.
Last weekend I was checking a video on Laravel 4 which was discussing about facades in Laravel 4 and I was truly amazed to see how the fancy looking static API’s are mapped into their original Classes. Laravel 4 takes advantage of Facade Design Pattern[ http://en.wikipedia.org/wiki/Facade_pattern ] which allows it to provide expressive syntax through static API’s but still keep it testable under the hood.
So, back to the main point of the post, how a static method like
1
|
|
is resolved under the hood. Let’s take File:get() and see how that maps to it’s original class. Seeing File:: I first though there must be a File.php some where where the static method will be available. Searched for that and found one at /vendor/laravel/framework/src/Illuminate/Support/Facades/File.php surprisingly it barely has any content in it. https://github.com/illuminate/support/blob/master/Facades/File.php
1 2 3 4 5 6 7 8 9 10 11 12 |
|
As I didn’t find a static get method there my second target was to search in the Facade Base class as File class was extending it. But there wasn’t any static get method either. But I did find a __callStatic magic method and became sure thats handling the call dynamically. You can check the contents of Facade.php here at https://github.com/illuminate/support/blob/master/Facades/Facade.php#L167
The first line in __callStatic method is
1
|
|
Where’s its calling the static resolveFacadeInstance() method and passing child class’s static method’s static::getFacadeAccessor() return value as a argument. Which is in above you can see returns the string ‘files’. Now lets look at the definition of resolveFacadeInstance()
1 2 3 4 5 6 7 8 9 10 11 |
|
First two conditions wont work for us. So it will return static::$app[$name]. What does $app[‘file’] have in it. Must be an instance of a class. To check this I was studying about the bootstrapping of Laravel 4 and found that at some point in booting up, Laravel 4 registers the service providers passed into it via /app/config/app.php file. And checking that I found a serviceproviders as follows
1
|
|
Then I checked the file Illuminate\Filesystem\FilesystemServiceProvider and found out how $app[‘files’] is being assigned. Here’s it’s contents
1 2 3 4 5 6 7 8 9 10 11 12 |
|
So $app[‘files’] is actually being assigned to a instance of FileSystem class. Laravel uses that register method to add that service in the $app container. So File::domeSomething() is actually somewhat equivalent to
1 2 |
|
And I did find a public get() method in the FileSystem Class. You can check here at https://github.com/illuminate/filesystem/blob/master/Filesystem.php#L27
So, a simple call like File::get() which just works, have a lot more going on under the hood.
The word File is actually an alias to the Facade at ‘Illuminate\Support\Facades\File’ which you can find at /app/config/app.php in alias block.
Thats true for most if not all(well I havent checked all, but lets hope so) static expressive API’s Laravel 4 Provide.
A quick way to check which Class is being mapped for a Facade by using a special route in the route file as follows
1 2 3 4 5 |
|
It will print the original Class that’s being used for the Facade.
I dont know why but finding the whole thing was a great joy for me. It always feels great to understand the inner working principle of a thing I am using. This is the most awesome thing I have learnt/known in a while.
Hope you enjoyed it. :D