تماشای این درس نیاز به اشتراک حرفه‌ای دارد.

Motivation for Refactor0:00

Now, at this point, you understand the basic Honeypot technique. So if you like, you can skip over this video and move on to the next section. But I'd like to stick around for one more video to discuss basic code structure and organization, as well as how to allow for extension and modification. Okay, so have a look at this. This Honeypot class is, in fact, a middleware, and we take care of all the Honeypot logic within it. So that's fine. But can you imagine a situation where you want to perform this Honeypot detection outside of an incoming request and outside of a middleware?

But can you imagine a situation where you want to perform this Honeypot detection outside of an incoming request and outside of a middleware? And sometimes the answer is yes. But at the moment, there would be no way to do that without repeating all of this code. So in those situations, the solution is to extract all of this into a different class. And then you delegate. You know, it's funny. Many years ago, I remember reading forum threads where people would ask, how do I call one controller from another controller? It's one of those first code structure things you try to solve.

controller from another controller? It's one of those first code structure things you try to solve. I have this logic in a controller over here, and I want to use it, but I'm in a different controller. So how do I call, quote unquote, one controller from another controller? And of course, the answer is, oh, you don't do that. You instead extract the logic you want to call into a service class or something similar. And then both of those controllers defer to that class using dependency injection. It's the same basic approach here. So think about it.

It's the same basic approach here. So think about it. If we were to rewrite this again, maybe I could say something like, if we had a Honeypot dependency, if we detect any spam, then abort. And we have that method here. So I could even pull that up. Otherwise, return to the next request. You know, ultimately, that's what we're doing. But in order to make it work, we had to add all of this logic here. All right.

Renaming the Middleware1:51

But in order to make it work, we had to add all of this logic here. All right. So let's see how we can get from here to here. Obviously, the first step is to add that Honeypot dependency. And then initialize it. But next, what is Honeypot? Well, it needs to be a class. And the obvious name for the class is Honeypot, but we already have that name used for the middleware. So, of course, we could be a little more specific.

middleware. So, of course, we could be a little more specific. I often try to avoid suffixes, though I'm kind of unreliable there. But instead, maybe let's be more specific. Let's bring it back and rename it to, what is it doing? This is blocking spam. So maybe I can just call it blockSpam. And then we will update all the references. And by the way, that should include the middleware reference here in my routes file. Okay.

Extracting Honeypot Class2:39

And by the way, that should include the middleware reference here in my routes file. Okay. So now I can create this new Honeypot class. And this is almost like the manager for the component. So if we come on back, we wanted to call it detect. So that's our first step. detect. Okay. Now it looks like really all of this chunk. Let's just start here.

Now it looks like really all of this chunk. Let's just start here. Let's move it all over like so. And then we'll start cleaning up. Now immediately, we never go on to the next request. So this would be effectively return false. We did not detect anything suspicious. Next abort. Maybe that is more appropriate for the middleware. So I will find all of these and instead return true.

Maybe that is more appropriate for the middleware. So I will find all of these and instead return true. We did detect something suspicious. So abort. Now if we switch back, you'll see, yep, if we detect anything, if that's truthy, then abort. Otherwise, we return false, which means we continue on to the next layer of the onion, so to speak. Okay. Next, we need access to the Honeypot configuration and the request data.

Injecting Request and Config3:44

Okay. Next, we need access to the Honeypot configuration and the request data. So that's our next step. In our constructor, this class depends on the current request as well as an array of configuration items. And I will initialize that like so. Now you can still do this if you want, by the way, line 21. But sometimes it's better to just accept it through the constructor. Okay, so now I'm going to find all these references to the config and update it. And then we'll do the same thing for all of these references to the request.

Okay, so now I'm going to find all these references to the config and update it. And then we'll do the same thing for all of these references to the request. Like so, and give it a reformat. Okay, next we have this time to submit form. And that existed down here. So why don't we grab that and move it over. And next, I don't love this name. Why don't we change it to, hmm, this is a wrapper for a form. We're really just checking if the form was submitted too quickly. So let's be very direct there.

We're really just checking if the form was submitted too quickly. So let's be very direct there. If it was submitted too quickly, then we should return true. Okay, next, we don't need to pass these through since they're on the constructor. So I can update that. Remove all of this. I should clean it up a little bit. Again, give it a reformat. Yeah, we're starting to get there. Next, we can even add additional helpers.

Yeah, we're starting to get there. Next, we can even add additional helpers. Like right here, we're checking if honeypot is enabled. You can do things like this, enabled. And then this method is responsible for looking into the config and checking that key. And then, again, if this is being used by many people, you might want to add additional helpers like disabled. And that would do the opposite, just to make it more readable and clear. But I'm not going to worry about that in this case.

And that would do the opposite, just to make it more readable and clear. But I'm not going to worry about that in this case. So now notice I can just say, well, if honeypot is not enabled, return false. Otherwise, then we look into the request. And you know what? You could even sometimes do things like this. If there's one way to detect based on some fields that you pass in, and another way to detect from the request data, yeah, in those cases, you might have a detect method, and then also a method called detectFromRequest. That's an approach you'll often see in a variety of areas.

Simplifying Middleware Usage5:48

you might have a detect method, and then also a method called detectFromRequest. That's an approach you'll often see in a variety of areas. But for now, we'll just assume it's always going to detect from the request. Okay, so that's looking decent to me. Next, if we come back to our middleware, have a look. We can get rid of all of this junk, and this is where we end up. And in fact, we've inlined it here, though I think ultimately we will keep that as an extracted method. But just for now, this is what you end up with, much cleaner. The only problem is right now, we're still not there yet.

But just for now, this is what you end up with, much cleaner. The only problem is right now, we're still not there yet. Give it a run, and yeah, as expected, it fails with the binding resolution exception. So it's trying to build up your middleware class, and it came to this constructor argument, and it has no idea what you want there. So let's give it a hint. We actually want an instance of Honeypot, so try to build that up for us. If we come back and give it another shot, it's still going to fail though, because now it's looking at the constructor for the Honeypot class, and

Binding in Service Container6:44

If we come back and give it another shot, it's still going to fail though, because now it's looking at the constructor for the Honeypot class, and it can take care of the request for you, but it has no idea what you want for this array. So in these situations, visit your Honeypot service provider, and then let's set up a singleton in this case. And we're going to put a key into the container for Honeypot. And when that's resolved, we're going to be explicit about what we want to return. Instantiate Honeypot, and for the request and config, we can just grab it like this.

Instantiate Honeypot, and for the request and config, we can just grab it like this. They're already in the container. The config repository will be under config, but I don't want the whole thing. We just want the Honeypot file, so just give me this array here. So now think about it. When Laravel tries to instantiate this class, it'll come across the Honeypot instance, and it's going to see, I already have something in the container with that exact key. So I'm just going to return what's associated with it,

I already have something in the container with that exact key. So I'm just going to return what's associated with it, which means this instance right here will be passed here. Okay, so now if you'd like to see this, let's dd and dump the Honeypot when the middleware runs. We give it another go, and sure enough, here's our new class with our request and our config items. All contained, perfect. So now we call detect. This detect method will do exactly what we had written an episode ago.

Testing Spam Detection8:06

So now we call detect. This detect method will do exactly what we had written an episode ago. And with any luck, it should work. So let's give it a refresh, trigger the spam detection, and it works. Let's come on back, and let's artificially, not artificially, but let's fill out just to simulate a bot. Run it, and that will trigger the spam detector as well. So again, now the benefit is if you ever need to run your Honeypot logic from outside of a middleware and outside of an incoming request, you can now do so.

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