The relationship between the container/serviceprovider/facade of Laravel

Source: Internet
Author: User
Tags bind redis

Briefly

When you come into contact with Laravel service Container, service provider,contracts and façade, you may already know what they are, but for how and when to use them, and what the relationship between them is, It's not very clear. And the point is that if you look at the document over and over again, you'll be trapped by it because there are some parts of the document that are misleading as well as unexplained; now we're going to take care of them at once;

Basic concepts

Before continuing this tutorial, you need to have a basic understanding of the above concepts and know what they are;

Service Container and service Provider

Service Container, the use of IOC containers, is not dependent on service Provider, for example:

$app->make (' app\models\post ');

This sentence is exactly the same as the new App\models\post; In addition, you use constructors in the controller, Type-hint for dependency injection, and there is no half-money relationship with service provider.

In short, you can completely not use service Provider;

Service Provider and Contracts

If the use of the IOC container does not depend on service Provider, then why do we always have to bind the service Provider in config/app.php when we download the expansion pack with composer? Sometimes it is necessary to bind the façade;

The idea of understanding is this, Laravel core class (Services) are composed of interface (contracts) + implementation, if not understand this concept, carefully look at the chapter of the document interface. While you are in use, if you want to get an instance of an interface implementation, need to use service Container, and to use service Container to resolve an interface, rather than directly parse a class, this time will use service provider, It can be said that the main function of Service provider is to bind the interface.

I'm going to talk about the pit dad thing, before the interface binding, first understand some basic facts:

Some facts

$app->make (' app\models\post ');

You can write this,

$app->make (' post ');

It can also be written, where the post is an alias, the alias is the main place to create confusion; this time you must be thinking, what is the use of this, where do I go to associate this alias to App\models\post?

The bind method of Service Provider

Yes, you bind the alias in the service provider using the Bind method:

$this->app->bind (' Post ', function ($app) {return new App\models\post;});

After this binding you can $app->make (' post '); So far there is no egg used. It's okay, I'll talk about it later, it has something to do with the façade; let's explain the document. Pit Dad's Place:

This is how the document writes the Bind method:

$this->app->bind (' Helpspot\api ',

function ($app) {

return new Helpspot\api ($app [' httpclient ']);}
);

Wow, your first parameter in the end of what Ah, in fact, the first parameter can fill in the full name of the class, but if it is not a short title, I do this binding have any meaning? Back to the same class instance? Hey? $app [' httpclient '] what is this?? In fact, it tells you that you can then inject an instance of another class when parsing a class. Document brother, please explain to me, can you give me an example of a reliable point ...

If you go to other extensions to see other people's bind, you will find strange binding writing, regardless of them, now we look at the service provider to the interface, the most basic principle is this:

Give an interface an individual name $this->app->bind (' Event_pusher ', function ($app) {return new App\contracts\eventpusher;}); /Specify the instance that this interface should parse $this->app->bind (' App\contracts\eventpusher ', ' app\services\rediseventpusher ');
Through these two steps, we let this interface have the alias, also has the parsing time corresponding realization;

In this way, we can:

$app->make (' Event_pusher ');

Get App\services\rediseventpusher;

Service Provider and facades

Let's look at the style of the façade, such as Illuminate\support\facades\cache:

Class Cache extends facade{

protected static function Getfacadeaccessor () {return ' cache ';}}

This cache is the alias mentioned above;

Now let's look at the corresponding diagram of the façade:

Façade Name façade class resolved class Service Provider Binding Alias
Cache Illuminate\support\facades\cache Illuminate\cache\repository Cache
So when you call Cache::get (' user_id '), you actually call the Illuminate\support\facades\cache class, and get is not the static method of this class, in fact, Get this method does not exist in the façade of the class, which is exactly what it was designed to do, when the get this method does not exist, it will call the façade base class in the __callstatic Magic method (need to understand this magic method in advance), this method will be the service The class (or interface) that is bound in the provider is parsed and returned, in this case, the Illuminate\cache\repository class, so get is actually a way of illuminate\cache\repository this class;

Then we look at the document again, some of the façade is not alias it? Like what:

Façade Name façade class resolved class Service Provider Binding Alias
Response Illuminate\support\facades\response
Illuminate\contracts\routing\responsefactory


Yes, you can directly write the full name of the class, not alias, if you look at this illuminate\support\facades\response source code, it is written like this:

Class Response extends facade{
protected static function Getfacadeaccessor () {

Return ' illuminate\contracts\routing\responsefactory ';

}}

The class can be returned directly;

What exactly is a façade's namespace?

We found that when using Cache::get (' user_id '), you can use using Cache; You can also use

Use Illuminate\support\facades\cache;

What is this for?

Don't forget, you've bound a façade alias in Config/app.php's class aliases, which is:

' Cache ' => illuminate\support\facades\cache::class,

With this binding, you can use the cache directly using the façade;

Add:


Container container

Let's say what the goods are for. Now let's say you want to do an open source project, write a class to implement some kind of function. OK, then let's assume that the work you have to do is more complex and requires

manipulating databases
Cache
manipulating static files
Action session
Wait a minute...... It's complicated to think, but it doesn't matter, and it's obvious from these few parts that they don't seem to have any connection. Then you can consider the above parts as a separate class, that is, for database operations we write a DB class encapsulation some common operations, for caching we write a cache class ...
Well, when you want to use this class, you might see this code

<?php
Class SomeClass {

Public Function Dbtask () {
$db = new Dbclass ([' localhost ', 3306,root,pwd]);
Database operations
}

Public Function Cachetask () {
$cache = new cache ([' localhost ', 11211]);
Caching operations
}
//...
}
It seems to be fine, but think about it, if SomeClass relies on a lot of external classes, every time we use SomeClass we have to take it into that class, and then instantiate that object by parameter, which is very troublesome. Then the concept of the container is produced.
What do you mean by container? Simply put, the service that our application might use (like the ones above, because a dedicated feature called them service) is all bound to a global object, which is called a container. Maybe it's like the following.

Class Container {

protected $service _arr = [];

Public function bind ($name, $instance) {

$this->servie_arr[$name] = $instance;

}

Public function Get ($name) {

return $this->service_arr[$name];

}

}
Then we will use some service later, we can directly through the Container->get (' some ') way to get the example

<?php
Class SomeClass {

Priavte $container;

Public function construct ($con) {

$this->container = $con;

}

Public Function Dbtask () {

$db = $this->container->get (' db ');
Database operations
}

Public Function Cachetask () {

$cache = $this->container->get (' cache ');
Caching operations
}
//...
}
OK, now you probably know what container is. To put it simply, the object that we might need to manually instantiate inside the code is bound to the container object, which we'll use to get here later. As for its benefits I will not go into the details, you can look at the design mode of the IOC and DI chapters (Control reversal and dependency injection)

ServiceProvider

If you understand the container above, you will have questions.

If you want to bind all possible service, will the container class become very large?
Yes, if you call the N-th bind method at the beginning of the application and bind all the required service in turn, the file will be difficult to maintain, such as

Class Container {

protected $service _arr = [];

Public function bind ($name, $instance) {

$this->servie_arr[$name] = $instance;

}

Public function Get ($name) {

return $this->service_arr[$name];

}

}

$con = new Container ();

$db = new Dbclass ([' Locahost ', 3306,root,pwd]);

$con->bind (' db ', $db);

$cache = new Cache ([' 127.0.0.1 ', 11211]);

$con->bind (' cache ', $cache);

//...
The instantiation of all classes is written into a file, which is coupled with a rise in coupling. ServiceProvider is the solution to this problem.
Each need to bind to the container service, you need to create a corresponding serviceprovider, this serviceprovider has a register method, which is bound here, not like the above. Like what:

Class Someserviceprovider extends ServiceProvider {

Public Function Register () {

$this->app->bind (' Some ', new some ());

}

}
Laravel container to know which service to bind, it reads an array, which is config/ The providers in the app.php, and then you just have to write your someserviceprovider into this array and you can bind to it.

Façade

Just start looking at the façade is still not very good understanding, in the end what is the façade, it is the meaning of what it is?
I understand.

Simplifies the use of service and can be understood as grammatical sugars
Easy to replace
Perhaps you have doubts about what to replace? Look at the code below.

Use Illuminate\support\facades\redis;

Class Indexcontroller extends Controller {

Public Function index () {

$redis = Redis::connect ();

Do something

}

}
However, when we open Illuminate\support\facades\redis to see

File

There is no static method of connect Ah? But the only way to find out is to return a Redis string, what's the mystery?
Then we'll look at Redisserviceprovider.

File our Redisserviceprovider a redis in the container ... So you probably guessed it too, right!

Redis::connect () is equivalent to $this->app->get (' Redis ')->connect ()
What the get is, depends on the string returned by the Getfacadeaccessor method in the façade!
What good is that? The document also says that, in addition to the simple use of the most useful is testing, think about it, you turn the Redis Getfacadeaccessor method return value to ' memcached ', then all you use Redis::some () is all switch to

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.