در حال بارگذاری ...

مرور آیا Laravel بیش از حد جادویی است؟0:00

One of the most common complaints about Laravel is that it's full of magic. Like, you know, things just happen, and you can't trace what's actually going on. And, you know, to be fair, if you're not familiar with metaprogramming of PHP, then, well, yeah, Laravel can feel like it's doing magic behind the scenes. But you know, here's the thing, Laravel's magic is just well-documented PHP features. And once you see the pattern, then the whole mystery just evaporates. I think the very first thing that we should do is demystify the whole thing.

Building a Magic Demo0:29

And once you see the pattern, then the whole mystery just evaporates. I think the very first thing that we should do is demystify the whole thing. Because, you know, as I mentioned, it's just metaprogramming in PHP. So let's make a new class. And what do we call this? Let's call this demo magic demo. And we essentially are going to want to do two things. Let's open up that magic demo class and we can have this constructor. That's perfectly fine. But really what we want to do is hook into PHP's ability to dynamically call

That's perfectly fine. But really what we want to do is hook into PHP's ability to dynamically call methods. There are two that we need to hook into. The first is called simply call. We're going to get to the method that we want to execute followed by an array of arguments that are passed to it. And all we are going to do is return that this is an instance call to the given method.

And all we are going to do is return that this is an instance call to the given method. And then we can also include the arguments as well. I guess let's do this. We'll just JSON encode the arguments and that's going to be fine. And then we'll just take that method and then we're going to copy it and paste it. And in this case, we're going to hook into the ability to call static methods. That's using the call static hook, which has the method, it has the arguments. And in this case, it's a static call, but this is it.

Testing Dynamic Calls1:54

That's using the call static hook, which has the method, it has the arguments. And in this case, it's a static call, but this is it. This is essentially the magic that PHP, well, yes, PHP, but also the magic that Laravel is built upon. And we could see this in action. Let's create a couple of routes. So let's have a get for demo dash instance, and all we are going to do is first of all create a new magic demo object so that then we can just return demo.

of all create a new magic demo object so that then we can just return demo. And you know, in this case, it doesn't matter. We can call any method that we want. In fact, we can just call it any method and we will pass in argument one, argument two, and we could keep adding arguments as we needed. But then just like how we copied and pasted for the instance method, let's do the same thing for the static and we'll call this route demo static.

the same thing for the static and we'll call this route demo static. And of course, in this case, we don't need to new up the magic demo constructor . Here we want to use the magic demo class so that we would call any static method passing in, let's just change these arguments just so that we know we have something a little bit different. So let's go to demo instance.

bit different. So let's go to demo instance. And we will see the instance call to any method with the arguments that we passed, then we want to look at the demo static and we see almost the same output. But of course, this is based upon calling a static method. We see the static call to any static method passing in the arguments. And that's the entire trick. Interval isn't doing any kind of wizardry. It's using PHP's dynamic dispatch hooks.

Interval isn't doing any kind of wizardry. It's using PHP's dynamic dispatch hooks. So if a method doesn't exist, PHP gives the class a chance to handle that method. And that's really how we get an API that is easy to read, easy to follow, and really easy to maintain. It's not magic. It's just a deliberate use of built in PHP features. Now this is going to take us to a discussion on facades.

Inspecting Facades3:58

It's just a deliberate use of built in PHP features. Now this is going to take us to a discussion on facades. And you know, we're not going to get into whether or not facades are good or bad. I personally like the use of facades, but you know, people think that facades are magic, but they're not. It's just a very specific use of PHP's features. Basically what we looked at with our magic demo. So let's do this.

Basically what we looked at with our magic demo. So let's do this. Let's take a look at facades, the actual source code. So if we go to vendor, then we need to find a Laravel, which is there, then framework, then source, then we need to scroll all the way down to support because there we can find the facades. That's where all of the facades live. And you know, let's pick cash.

That's where all of the facades live. And you know, let's pick cash. So if we look at the cash facade, it's a very simple class. There's this get facade accessor. And then there's this spy method. Now the spy method really doesn't help us for this discussion. All we really need is this get facade accessor method. And that's it. You know, so when we use the cash facade, you know, we are calling a static get method

You know, so when we use the cash facade, you know, we are calling a static get method or a put method, you know, things to interact with the cash, none of that is listed here. But we can see that the cash class extends the facade class. So if we take a look at the facade class, there's a lot here. But if we scroll all the way down pretty much to the bottom, here we can see the call static hook. So the facade is just a proxy, because what does it do?

hook. So the facade is just a proxy, because what does it do? It gets the facade root, it gets the instance of whatever service the facade is providing access to. And then using that instance, it calls the method. So in the case of the cash, you know, there's this get facade root. So if we take a look at get facade root, it simply gets the facade instance of the get facade accessor.

the get facade accessor. What is that accessor for the cash? It's cash. So it's reaching into the service container to get to the cash manager. And then that's it. It calls the appropriate method on the cash manager to either get or put information or to put data into the cash or get it out. So once again, there's no magic here.

Tracing Facade Access6:14

to put data into the cash or get it out. So once again, there's no magic here. A facade is just a proxy to give us an easy way of reaching into the service container to get whatever service that we need to work with. Now we can actually see this in action. So we're going to create a new route. And let's call this route facade trace, of course, one of our function to handle this. And the very first thing that we are going to do is put something into the cash

handle this. And the very first thing that we are going to do is put something into the cash . Let's use the key of demo, the value of Lara casts, and the time to live. It'll just be 60. Now, of course, we do need to pull in the cash facade, which is from support facades. And there we go. We have put something into the cash. Now, of course, let's pull data out of that.

We have put something into the cash. Now, of course, let's pull data out of that. So what we're going to do is, first of all, pull data from the cash using the cash facade. With the get method, we want the demo there. But then we are going to essentially get the cash repository from the service container and then retrieve the same data that way. So we want the repository class. It helps if you type repository correctly.

So we want the repository class. It helps if you type repository correctly. And we want the one illuminate cash repository. That's the repository class that we want. So this is going to give us the repository class that we have pulled out of the service container so that then we will have, we'll call this via container. And we will use the repository to get the value with the key of demo. So now we could just output that information so that we'll have via facade will be the

So now we could just output that information so that we'll have via facade will be the same as the value of via facade. And then we will have via container will have the value of via container. That's all that we really need to do so that then we just need to go to facade trace. And there we go. We can see that the value from the cash facade is lower cast. The value from the container is lower cast. So we are using the same cash object.

Logging Container Resolution8:14

The value from the container is lower cast. So we are using the same cash object. We just retrieved it in different ways, except that the facade gave us a much easier way of working with the cash than fetching it ourselves from the service container. But then that takes us to the service container. The service container seems magical. It seems like everything is hidden. And we can't see what is actually being resolved. Well, actually we can.

And we can't see what is actually being resolved. Well, actually we can. Let's go to the app service provider and inside of the boot method, we are going to essentially handle the resolving event. This is of course going to require a function that we passed to it. And we're going to get something that I'm just going to call an object. Sometimes it's not an object, which is actually something that we need to check for. So if it is not an object, well, then we don't want to do anything.

for. So if it is not an object, well, then we don't want to do anything. We just want to return because essentially what I want to do here is for every item that is resolved about the container, I want to log it. Now we have to be careful here because there are a lot of things that are resolved, including writing to the log. So what we're going to do is create our own log. So inside of storage, we are going to create logs slash resolving log.

So what we're going to do is create our own log. So inside of storage, we are going to create logs slash resolving log. And we essentially want to describe what is being logged here. So let's add the current date and time, we'll say resolving. And then we will include the class name for the object that is currently being resolved. We want that on a new line. And we want to append this. We don't want to override it every time. So file append there.

We don't want to override it every time. So file append there. And that's essentially what we want. So any time that the service container is going to resolve something, if it is an object, then we are going to write it to our resolving log show what is being resolved. And there we go. So let's make a new controller and we'll call it resolve log controller. And let's make this invocable because we don't really need to do really anything else except

And let's make this invocable because we don't really need to do really anything else except just display this information. So with that done, let's open up resolve log controller. And let's do this. Let's have the public function will have our constructor here. And this is going to get our cache repository and let's just call it cache there so that then whenever the controller is in vote, we will put something into the cache. Now, you know, we could be using the cache facade here, but we're going to

then whenever the controller is in vote, we will put something into the cache. Now, you know, we could be using the cache facade here, but we're going to resolve. We're going to resolve this repository class so that it's going to put something here. And we can just say from controller, let's have some kind of value. Yep. And let's have the time to live to be 60. And then just so that we have something to see inside of the browser, let's just return

And then just so that we have something to see inside of the browser, let's just return okay there so that then we just need to set up our route and that will be a get request. Let's call this resolve what log or just resolve. Let's call it resolve trace. I'll make it my mind eventually and we don't need an action because we have that resolve log controller class. So with that in place, we can go to the resolve trace URL, we see okay.

log controller class. So with that in place, we can go to the resolve trace URL, we see okay. So theoretically, there weren't any issues as far as that is concerned, but we can go to the storage folder, let's open up logs, and there we have our resolving log. So if we take a look, there are a lot of things that were resolved. That can't be, is that just one request? We can delete everything there, we can go back, we can refresh. And whenever we take a look, okay, no. So for one request, there were 47 resolutions, but the key thing to take away

And whenever we take a look, okay, no. So for one request, there were 47 resolutions, but the key thing to take away here is that we can hook into this resolving event. So we can see what is being resolved. And if we need to do something special for some kind of resolution, then we can do that. It's not magic because we can literally see what is being resolved. Now, there's one other angle that we need to look at and it's one that's really easy

Tools Understand Laravel12:37

Now, there's one other angle that we need to look at and it's one that's really easy to miss. Okay. And if Laravel was truly magical, our tools wouldn't know what to do with a Laravel project. And that's just not true. I'm using Visual Studio code and granted I do have the Laravel extension installed. That's hard to say, but my code editor knows what's going on and really I could

installed. That's hard to say, but my code editor knows what's going on and really I could uninstall the Laravel extension and I could just use some generic PHP extension and it's still going to work. It's still going to know the different pieces of my application and it's going to be just fine. The Laravel extension adds a little bit of extra stuff, yes.

fine. The Laravel extension adds a little bit of extra stuff, yes. But in the grand scheme of things, I don't have to have that to build an application and be productive because my tool will still understand it. And it's not just Visual Studio code. It's really any code editor that understands PHP, but it's not just code editors. It's, you know, tools like PHP Stan or Saul. It's really any tool that we use when building our application to either write

It's, you know, tools like PHP Stan or Saul. It's really any tool that we use when building our application to either write code or be sure that we have quality code or to test our code. All of our tools can understand our Laravel projects because the framework patterns are consistent and inspectable. So yes, Laravel can see magical, but it's all because of meta programming. It's not to obscure really anything. It's just to create clean and readable and maintainable APIs.

It's not to obscure really anything. It's just to create clean and readable and maintainable APIs. The magic is just PHP doing what PHP does. And if you spend just five minutes tracing a facade or watching the container resolve dependencies, then really the mystery just evaporates.

دوست دارید گاهی خبرهای Laracasts را ایمیل کنیم؟