مرور توضیح دهید که یک Facade در پشت صحنه چگونه کار میکند0:00
First up, we have a question that sweeps the entire Laravel framework. We're going to talk about gates, facades, namespacing, and the service container. All right, let's look at this question really quick. This person is trying to figure out how it is that we can reference the Gate class from the global namespace route, because he noticed if you take a look and you search, there's three Gate classes, and that's kind of confusing. But each of those classes is fully namespaced. They're not in the global route. So how is it that we're able to access it like so? And in this case, I don't have anything to check, but if we run it, it's not going to
Class Aliases Explained1:00
So how is any of this possible? All right, lots of things to review here. Let's take it piece by piece. First, how are we able to access this from the global namespace route? The answer is through a class alias. Go into your config/app.php file, and if you scroll down a ways, you'll come to this section, class aliases. This array of class aliases will be registered when the application is started. So if I scroll down, sure enough, we have an alias right here. Gate is an alias for this full path to the Gate facade.
So if I scroll down, sure enough, we have an alias right here. Gate is an alias for this full path to the gate facade. And in fact, if you want to verify it, let's comment out that key value pair. And if I boot up php artisan tinker again, and we try to run it, it will throw an error because we no longer have that alias. That answers that question. But if you're curious, if you want to dig even further and figure out, well, how exactly is Laravel doing that? There's a number of things. But again, ultimately, it's delegating to PHP's class alias function.
How Facades Register1:56
There's a number of things. But again, ultimately, it's delegating to php’s class alias function. So if you want to take a look, let's do the rapid 30-second review. If you go to your Kernel class, and then you visit the main Illuminate\Kernel class that it extends, if you scroll down, you'll see this section here. Register facades. Obviously, that's what we want. If we take a look here, when it gets bootstrapped, we're going to delegate to this alias loader and ultimately call a register method to register the aliases. Now you'll see to that singleton, we look in the config directory, we look in the app
and ultimately call a register method to register the aliases. Now you'll see to that singleton, we look in the config directory, we look in the app file, and then we read that aliases array, which is this right here. So all of these are being passed to the alias loader. Where we then call a register method. The register method prepends to the loader stack. It adds this to the auto loader. And if we take a look at that, ultimately, yeah, it's delegating to class_alias. So again, I don't expect you to understand every step of that. We went way too fast for it.
So again, I don't expect you to understand every step of that. We went way too fast for it. But the main thing to recognize here is any of the values here will ultimately be registered as class aliases. So if we switch back, I can't use it here. We try to run it. It doesn't work. But if you did it manually, you could say register a class alias. We're going to get the full path to the Facade. And then the alias is called gate.
Facade Static Dispatch3:39
All right, so that answers question number one. How is it that we're able to use this globally? Question number two gets a little more tricky. He noted on the Gate facade that those methods like allows and denies, they don't exist. They're not defined here anywhere. We can see these comments that signal to us we can trigger them. But if you're new to Laravel, very, very confusing. Okay, this is just something to understand. In Laravel, a facade provides a clean and quick access to an underlying object, which is why I can say Gate::allows here.
In Laravel, a facade provides a clean and quick access to an underlying object, which is why I can say gate allows here. And what's ultimately happening is a gate instance is being resolved out of the container. And then we're calling an allows method like so. So let's figure out how exactly that happens. You can see here you're calling a static method on this facade, but this facade doesn't have any method called allows. So if we go to the parent class, that means it's going to trigger a call static method. This is a magic method in PHP that will be triggered anytime you call a static method on a class that has not been defined.
This is a magic method in php that will be triggered anytime you call a static method on a class that has not been defined. All right, so let's see. We're trying to get an underlying root object. So we're trying to fetch the object associated with this facade. And then ultimately, we're delegating. So this would be the same as saying, get that underlying gate instance, whatever it is, and then we're going to call whatever you triggered here. And allows method with this key, like so. But now, yeah, it's still a little confusing.
Resolving From Container5:05
And allows method with this key, like so. But now, yeah, it's still a little confusing. How exactly are we associating this facade with an underlying class? All right, let's take another step. This is where we try to figure it out. Get facade root. So if we take a look at that, resolve facade instance. So we're trying to get something out of the service container, and we're passing to it this get facade accessor method. Well, we did see that defined on our facade class here.
this getFacadeAccessor method. Well, we did see that defined on our Facade class here. And as it turns out, every facade class in Laravel needs to include this method, whether it's the FileFacade. If we scroll down, getFacadeAccessor. Or the ConfigFacade, let's see if I can find that. Scroll down. Once again, getFacadeAccessor. This method for each facade will return some string that will be stored in the service container as a key.
This method for each facade will return some string that will be stored in the service container as a key. That's it. It's just an identifier. It's a key for the facade. Okay, let's switch back. So now we know that getFacadeAccessor for Gate is this class path to the Gate contract. All right, now we're going to resolve facade instance. So we take another step. First it checks, are we dealing with an object?
So we take another step. First it checks, are we dealing with an object? But that's not our case, and it's pretty rarely the case. First we're checking, well, have we already done this in a prior iteration? In that case, just return the cached version. This is what we really want, though. We're going to write to a resolved instances array, so we're going to cache it. And specifically, we're going to look in the Laravel service container and resolve the value of that key. So we're going to resolve this out of the service container.
value of that key. So we're going to resolve this out of the service container. This might be confusing, but if you've ever seen something like this, where we use the app helper function, that's all we're doing. Or you might see resolve, or you might see something like that. They're all going to do the same thing. We are resolving something out of the service container. So think of the service container in a very simplified way. Think of it like an array on steroids. It's this place where you can store any number of bindings.
Think of it like an array on steroids. It's this place where you can store any number of bindings. So what we could say is, for this key here, this string, gate contract, I want to associate that with some kind of object, some kind of instance. And that way, when you grab it out of the container, all you have to do is give us the key. Laravel's then going to look in its array and say, all right, I need something for this key. Give me the instance or the object associated with it. And that's basically it.
Give me the instance or the object associated with it. And that's basically it. So now you know when you say Gate allows, well, yes, it's true, there is no allows method on the facade. But we're not calling that method. We're instead calling the magic method that will then figure out what class is associated with that facade. It then resolves it out of the service container and then calls an allows method on that. And we can even verify this ourselves. If we know that the Gate facade ultimately points to a value associated with this key.
Service Providers Bindings8:35
But now there's one final piece of the puzzle that might be confusing you. You might think, all right, I get this. However, we are referencing an interface here, yet Laravel knew to return an implementation of that interface. How on earth did it know that? So if we run this like so, we're giving it the key, which is a class path to the contract. But what we actually got was an instance of this Gate class. How is that possible? And the answer is service providers. So again, we're doing a full sweep over the Laravel code base here.
And the answer is service providers. So again, we're doing a full sweep over the Laravel code base here. Lots of things to touch on. Now let's say you wanted to research this yourselves. I can take you directly there. But yeah, you may not always know where to look, but you do know how to search. So when in doubt, always just look for the class in question. And here you can see, all right, we know about that Gate class, but I also see an AuthServiceProvider. What is that?
provider. What is that? Okay, service providers in Laravel are sort of like the building blocks or the handshake for the various components. Each of these classes will register the component with the framework. And often, this includes adding bindings into the service container and other things of that nature. It's just like a handshake. It says, hi, Laravel. Nice to meet you.
It says, hi, Laravel. Nice to meet you. Here are some things I need to do to get my component up and running with the framework. And in fact, down the line, if you ever write your own packages, those packages will include service providers that register themselves with the framework. Okay. So let's take a look at this one. If I scroll down, you'll see register access gate. And if we take a look at that, this is the secret sauce that associates this string with this instance.
And if we take a look at that, this is the secret sauce that associates this string with this instance. Take a look. This app. So whenever you're referencing app, think of it as the service container, the application. And we're adding a singleton, and we're referencing this string. So notice this matches up with this. Now if we're thinking in terms of an array on steroids, this is the key, and this is the value. The key is gate contract.
the value. The key is gate contract. The value is an instance of what we actually want. It's the underlying instance with all of the necessary constructor args passed in. And in fact, you can test this. If you were to dump and say, hello, let's run this again. I'm going to resolve this key out of the container. And sure enough, it's calling this function right here, at least the first time. Every other time it will be cached because we're dealing with a singleton there. But we get this in response.
Every other time it will be cached because we're dealing with a singleton there. But we get this in response. So now we know if I make a request to resolve this out of the container, Laravel looks into its glorified associative array. Hey, I need something for this key. So it looks, and it sees, all right, well, we do have this registered in here. So we're going to return this Gate instance. We're going to return the value associated with that key. That's ultimately what's happening here. It's a little more fancy than that, but at a simple basic level, that's what's happening.
Custom Container Binding11:34
That's ultimately what's happening here. It's a little more fancy than that, but at a simple basic level, that's what's happening. And in fact, this is not limited to the Laravel framework. You can and will do this on your own. For example, let me just do it directly in my routes file. I could say, app, I'm going to register a singleton for foo, and this is going to return anything I want, even another string if I want, or it can return an instance of something important or a domain specific for my application. It's the exact same logic. So if we try this again, and I say, all right, I want to resolve the value associated with
It's the exact same logic. So if we try this again, and I say, all right, I want to resolve the value associated with foo, sure enough, we get that value. It's the same thing. So notice we covered the full spectrum of Laravel there. You learned that when you reference Gate in the global namespace Route, that's available because it was defined as a class alias right here. Next you learned that actually points to a Facade, which means when you call Gate::allows, you're not calling an allows method on the Facade, you're calling an allows method on the underlying object that is associated with the Facade.
you're not calling an allows method on the facade, you're calling an allows method on the underlying object that is associated with the facade. The facade declares a key that will be stored in the service container, and then when we resolve it, take a look at this, getFacadeRoot, we try to resolve it, we pass in that key for the service container, and then right here, we look into the app and we try to resolve it. That's what gives us our instance. Finally, you learned that service providers can register keys and their respective values in the service container like so. In this case, it's a singleton, but often it'll simply be a standard binding. Bind this key to this value in the service container.
In this case, it's a singleton, but often it'll simply be a standard binding. Bind this key to this value in the service container. And that way later, if I ever need to resolve it out of the service container, I can do it just like this. All right, hopefully that answers the question.
