How do I create a facade class with Laravel?
Step 1
Create a folder called facades
in your app
folder (app/facades
).
Step 2
Add the facade folder to your composer autoload.
"autoload": {
"classmap": [
...
"app/facades"
]
},
Step 3
Create a Facade file in that folder (FooFacade.php
) and add this content:
<?php
use Illuminate\Support\Facades\Facade;
class MyClass extends Facade {
protected static function getFacadeAccessor() { return 'MyClassAlias'; } // most likely you want MyClass here
}
Step 4
Create a model in app/models
(MyClass.php
).
<?php
namespace MyNamespace;
use Eloquent; // if you're extending Eloquent
class MyClass extends Eloquent {
...
}
Step 5
Create a new service provider (you can create a folder in app called serviceproviders
and add it to composer autoload) (app/models/MyClassServiceProvider.php
).
<?php
use Illuminate\Support\ServiceProvider;
class MyClassServiceProvider extends ServiceProvider {
/**
* Register the service provider.
*
* @return void
*/
public function register() {
$this->app->bind('MyClassAlias', function(){
return new MyNamespace\MyClass;
});
}
}
Here you can add new binding if you want another facade (don't forget to create a facade file if so).
Step 6
Add the service provider to the providers
array in config/app.php
.
'providers' => array(
...
'MyServiceProvider'
)
Step 7
Run composer dump
so we can access our new classes.
Step 8
You can now access MyClassAlias::method()
as a facade.
How do I inject a request into a facade class in Laravel?
Looks like this worked out:
In the ParamsServiceProvider, instead of using App::bind to instantiate the Params class, do this instead:
public function register()
{
App::alias(Params::class, 'params');
}
then the request object will be injected properly into the facade.
How and where does the Facade class property $app get set?
Found it there is a setFacadeApplication( $app )
method which is set on the initialization of the Laravel App.
How facades work in laravel? How the methods can be accessed with ::
The magic happens in Facade
's __callStatic
function.
public static function __callStatic($method, $args)
{
$instance = static::getFacadeRoot();
if (! $instance) {
throw new RuntimeException('A facade root has not been set.');
}
return $instance->$method(...$args);
}
It first gets the appropriate instance, and then simply invokes the requested method with the given arguments.
Adding Facades before namespace in Laravel , How it works?
What you are describing is Laravels Real-Time Facades.
You can find documentation of the functionality here:
https://laravel.com/docs/6.x/facades#real-time-facades
How laravel uses object as an array in Facade class
Clicking through the Laravel source, I found this. As you can see, ApplicationContract
(the private static $app
from your question) is implemented by Application
. This is in turn derived from Container
, which implements the PHP core ArrayAccess
interface. Carefully implementing this whole chain eventually makes Applicatin
accessible like an array.
Turns out it boils down to good ole' object oriented programming :)
// Illuminate/Foundation/Application.php
class Application extends Container implements ApplicationContract, HttpKernelInterface
^^^^^^^^^ ^-> the private static $app in your question.
// Illuminate/Container/Container.php
class Container implements ArrayAccess, ContainerContract
^^^^^^^^^^^
// PHP core ArrayAccess documentation
/**
* Interface to provide accessing objects as arrays.
* @link http://php.net/manual/en/class.arrayaccess.php
*/
interface ArrayAccess {
How to Set Up Facades in Laravel 5.2 (outside of /app)
This may not be the only way to implement facades in Laravel 5, but here is how I did it.
We're going to create a custom Foo
facade available in the Foobar
namespace.
1. Create a custom class
First, for this example, I will be creating a new folder in my project. It will get its own namespace that will make it easier to find.
In my case the directory is called Foobar:
In here, we'll create a new PHP file with our class definition. In my case, I called it Foo.php
.
<?php
// %LARAVEL_ROOT%/Foobar/Foo.php
namespace Foobar;
class Foo
{
public function Bar()
{
return 'got it!';
}
}
2. Create a facade class
In our fancy new folder, we can add a new PHP file for our facade. I'm going to call it FooFacade.php
, and I'm putting it in a different namespace called Foobar\Facades. Keep in mind that the namespace in this case does not reflect the folder structure!
<?php
// %LARAVEL_ROO%/Foobar/FooFacade.php
namespace Foobar\Facades;
use Illuminate\Support\Facades\Facade;
class Foo extends Facade
{
protected static function getFacadeAccessor()
{
return 'foo'; // Keep this in mind
}
}
- Bear in mind what you return in
getFacadeAccessor
as you will need that in a moment.
Also note that you are extending the existing Facade class here.
3. Create a new provider using php artisan
So now we need ourselves a fancy new provider. Thankfully we have the awesome artisan
tool. In my case, I'm gonna call it FooProvider
.
php artisan make:provider FooProvider
Bam! We've got a provider. Read more about service providers here. For now just know that it has two functions (boot
and register
) and we will add some code to register
. We're going to bind our new provider our app:
$this->app->bind('foo', function () {
return new Foo; //Add the proper namespace at the top
});
So this bind('foo'
portion is actually going to match up with what you put in your FooFacade.php
code. Where I said return 'foo';
before, I want this bind to match that. (If I'd have said return 'wtv';
I'd say bind('wtv',
here.)
Furthermore, we need to tell Laravel where to find Foo
!
So at the top we add the namespace
use \Foobar\Foo;
Check out the whole file now:
<?php
// %LARAVEL_ROOT%/app/Providers/FooProvider.php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Foobar\Foo;
class FooProvider extends ServiceProvider
{
/**
* Bootstrap the application services.
*
* @return void
*/
public function boot()
{
//
}
/**
* Register the application services.
*
* @return void
*/
public function register()
{
$this->app->bind('foo', function () {
return new Foo;
});
}
}
- Make sure you use
Foobar\Foo
and notFoobar\Facades\Foo
- your IDE might suggest the wrong completion.
4. Add our references to config/app.php
Now we have to tell Laravel we're interested in using these random files we just created, and we can do that in our config/app.php
file.
Add your provider class reference to
'providers'
:App\Providers\FooProvider::class
Add your facade class reference to
'aliases'
:'Foo' => Foobar\Facades\Foo::class
Remember, in aliases, where I wrote 'Foo'
, you will want to put the name you want to reference your facade with there. So if you want to use MyBigOlFacade::helloWorld()
around your app, you'd start that line with 'MyBigOlFacade' => MyApp\WhereEverMyFacadesAre\MyBigOlFacade::class
5. Update your composer.json
The last code change you should need is to update your composer.json
's psr-4
spaces. You will have to add this:
"psr-4": {
"Foobar\\" : "Foobar/",
// Whatever you had already can stay
}
Final move
Okay so now that you have all that changed, the last thing you need is to refresh the caches in both composer and artisan. Try this:
composer dumpautoload
php artisan cache:clear
Usage & A Quick Test:
Create a route in app/routes.php
:
Route::get('/foobar', 'FooBarController@testFoo');
Then run
php artisan make:controller FooBarController
And add some code so it now looks like this:
<?php
namespace App\Http\Controllers;
use Foobar\Facades\Foo;
use App\Http\Requests;
class FooBarController extends Controller
{
public function testFoo()
{
dd(Foo::Bar());
}
}
You should end up with the following string:
Troubleshooting
- If you end up with and error saying it cannot find the class
Foobar\Facades\Foo
, try runningphp artisan optimize
Why create a facade in laravel instead of calling a method directly?
A Facade in Laravel is only a convenient way to get an object from the Service Container and call a method on it.
So calling a Facade like this :
//access session using a Facade
$value = Session::get('key');
Is like doing:
//access session directly from the Service Container
$value = $app->make('session')->get('key');
As the Facade resolves the session
key out of the Service Container and call the method get
on it
Once understood what a Facade does, you should understand what is the Service container and what are the benefits of using it
The Service Container in Laravel cloud be a Dependency Injection Container and a Registry for the application
The advantages of using a Service Container over creating manually your objects are stated in one of my previous answers and in the doc page, but briefly:
- Capacity to manage class dependencies on object instantation
- Binding of interfaces to concrete classes, so that when a interface is requested in your program, a concrete class is instantiated automatically by the service container. Changing the concrete class on the binding, will change the concrete objects instantiated through all your app
- Possibility to create single intances and get them back later (Singleton)
What is Facades used in Laravel?
Props to SitePoint for sharing such informative and helpful knowledge about facades in Laravel.
The facade pattern is a software design pattern that is often used in object-oriented programming.
A facade is a class wrapping a complex library to provide a simpler and more readable interface to it.
Facades in Laravel
Facades provide a "static" interface to classes that are available in the application's service container. Laravel ships with many facades which provide access to almost all of Laravel's features. Laravel facades serve as "static proxies" to underlying classes in the service container, providing the benefit of a terse, expressive syntax while maintaining more testability and flexibility than traditional static methods.
How Facades Are implemented in Laravel
Every service inside the container has a unique name. In a Laravel application, to access a service directly from the container, we can use the App::make()
method or the app() helper function.
<?php
App::make('some_service')->methodName();
In Laravel, all services have a facade class. These facade classes extend the base Facade class which is part of the Illuminate/Support
package. The only thing that they need to implement is the getFacadeAccessor method, which returns the service name inside the container.
Related Topics
Is There a JavaScript Way to Do File_Get_Contents()
Pdo: Invalid Parameter Number: Mixed Named and Positional Parameters
Xml Parse Error - Extra Content at the End of the Document
Mysql_Connect(): No Connection Could Be Made Because the Target MAChine Actively Refused It
Why Does This Return Resource Id #2
Php: Strtotime Is Returning False for a Future Date
Concatenate Values of N Arrays in PHP
Sort Multidimensional Array by Date Column, Then Use Other Column Values If Dates Are the Same
How to Set Cron Job Through PHP Script
Cross Domain Ajax Request with Jquery/Php
How to Properly Use Bearer Tokens
Parallel Processing in PHP - How to Do It
Is_Null($X) VS $X === Null in PHP
Laravel Eloquent Update Just If Changes Have Been Made
How Come Checkbox State Is Not Always Passed Along to PHP Script