Refactoring note fetch0:00
All right, welcome back everybody, let's jump right in. So I will return to our NoteController from the previous episode, and yeah, here's where we left off. So I want to point your attention to all of this junk here. All of this is responsible for fetching a note from the database and authorizing it. So why don't we see if there are small little tweaks and refactors that we might use to clean this up a bit? Because remember, this is what 80% of programming is. You get the first draft on paper, so to speak, and then you go over it again and again and again, making microscopic improvements that really do add up at the end of the day.
do that automatically for me. Think about it. If I had that fetch method, if that method was available to me, I would no longer have to write this. And in fact, across the entire code base, I would no longer have to write logic like this. I would simply use a helper method like that. But the problem is, well, this fetch method, I don't own. That's something that php provides internally. I think it's actually a PDOStatement class. In fact, let's just play around.
I think it's actually a PDO statement class. In fact, let's just play around. Let's die and dump the note to see what we have here. So I'll come back, give it a refresh, click on a note. And yeah, we see we have an instance of a PDO statement class that I don't own. But yeah, it's true though, there will be situations where you wish you did own it so that you could add things, so you could stack things like this. So is there a way that we can allow for this? And the answer is absolutely. There's a number of options that we might consider.
Returning DB instance2:08
But again, what if it didn't? Hmm, well, if it didn't, maybe I could either wrap it inside of another object or simply extend the API of this Database class to offer some additional helper methods. All right, come along for the ride and see what you think. If I'm no longer returning the statements, well, I could just return the object itself, the instance. And we can do that by saying return $this. Okay, so now when I call query, I'm not returning that PDO statement, I'm returning the same instance of Database. So in fact, right now, everything's going to blow up, of course, because now we're trying
instance of database. So in fact, right now, everything's going to blow up, of course, because now we're trying to call fetch on a database class, and it doesn't exist. So yeah, if we come back to Firefox and refresh, of course, we get a fatal error, and we'd expect that. There is no fetch method on the database class. Okay, so you know what? Let's do baby steps here. Why don't we start by adding a fetch method? So I will switch back, scroll down, and we'll add it here, fetch.
Storing PDO statement3:00
Why don't we start by adding a fetch method? So I will switch back, scroll down, and we'll add it here, fetch. And yeah, this is basically going to do what we had earlier, where we'd have something like statement->fetch. But now the problem is, this statement object, I don't have access to it. It's outside of the scope of this method. And instead, it's inside of query, right? Here's our statement, and I want to access it from this method, but I can't do that. So it sounds like, hmm, there's a couple ways we could do this. But it sounds like, why don't we assign the PDO statement to this object as an instance.
So it sounds like, hmm, there's a couple ways we could do this. But it sounds like, why don't we assign the PDO statement to this object as an instance property, like this? This statement equals connection prepare. And then I can update this like so. And then finally, I will declare it at the top. Now, don't forget, at the moment, we are making all class properties or object properties public because we haven't yet reviewed visibility or types or any of that stuff. But yeah, again, in real life, this would probably be protected or private. But for now, public is fine.
But yeah, again, in real life, this would probably be protected or private. But for now, public is fine. Okay, cool. So now that we've effectively assigned the PDO statement to the object, I can grab it from any method that needs to access it, like this. So I'm going to say return $this->statement->fetch(). And if we did everything correctly, it all should just work. Come back to Firefox, give it a refresh, and there we go. We're in business. But now the key difference here, and this is an important one, the key difference is
We're in business. But now the key difference here, and this is an important one, the key difference is that I now own this fetch method, which means if I don't want to call it fetch, as an example, I don't have to. And in fact, I think fetch is an ideal. If I just want to grab a record, if I want to find a record, well, why don't I just use a method like find? Well, now I have that ability because, again, I own this method. Okay, so now if I come back to note, you'll see by making this refactor, or again, we could have wrapped up the PDO statement within our own class and our own object that would
Adding findOrFail5:23
Okay, so now we've swapped it over to find, everything still works, and this is looking great. So the next step is to add a method to handle this. And remember at the beginning of the video, I said it might be nice if there was a method called fetch or abort, or find or abort, or find or fail, whatever you want. Again, this is the creative aspect of programming. You get to name it whatever you want. So in our case, why don't we call it findOrFail? Okay, and that would ideally, if we do it right, that would allow us to remove all of this here and everything would still work just like it did before.
Okay, and that would ideally, if we do it right, that would allow us to remove all of this here and everything would still work just like it did before. All right, well, let's do it. Back to our Database class. We now have a find method, but I will add a second version, findOrFail. And this is just going to say, all right, we'll try to find the record. So this is going to call that other method that we just created. But then we're going to do a check here, and we'll say, remember, I can't just say note because it won't always be a note. It could be a User.
note because it won't always be a note. It could be a User. It could be a Post. It could be something different. So we want to keep this fairly generic, like result. Then I could say, all right, well, if there's not a result and we're just reproducing what we had in that NoteController, then abort. But otherwise, if we do have a result, I can return it. And yeah, if we did everything correctly, this should just work. Let's give it a shot.
And yeah, if we did everything correctly, this should just work. Let's give it a shot. We'll go into this note. And yeah, let's now access a note that doesn't exist. And we get a 404. It works exactly the way it did before. But now we've wrapped up this incredibly common logic that you can imagine needing to perform throughout your entire code base. So I think that's a pretty cool refactor. Let's come back to our NoteController.
Creating authorize helper7:05
So I think that's a pretty cool refactor. Let's come back to our NoteController. And now it's a little more simple. All right, next, let's move on to this section here. And again, sometimes it helps to take a step back and just ask yourself, well, what is this code doing? And if I were to explain it to you, I would say, oh, this code authorizes that the current User created the given Note. But notice that keyword authorize doesn't exist here. But maybe it should.
But notice that keyword authorize doesn't exist here. But maybe it should. So in that case, maybe we could add a helper function called authorize. Let's try it out. If we, and this doesn't exist right now, but if we had a function called authorize, what would we do? Well, maybe we could take the condition and pass it through. And that would just do it. You know, again, wouldn't it be cool if that was a thing? And if it's not a thing, make it a thing like this.
You know, again, wouldn't it be cool if that was a thing? And if it's not a thing, make it a thing like this. We'll go into functions.php. We're going to add a new one here, authorize. This will accept some kind of condition or really a Boolean. And then I could say, well, if the condition fails, so if not condition or falsy, then we will abort with a 403 if you wish. So response forbidden. And I think that should do it. And actually, on this note, it might be useful and flexible if we extended this.
And this is where in the future you'll learn about testing automated ways to confirm that you didn't screw up, as I did here. So anyways, if I come back to our NoteController, I want to authorize that the note's userId equals the current user. And that'll solve the problem, as you see there. Finally, if we view a note that we did create, everything works the way we'd expect. OK, so let's wrap up by updating. And does this fail? Yeah, it does. So because we made those tweaks to the Database class, we're going to have to update our notes.
Renaming fetchAll to get10:59
Yeah, it does. So because we made those tweaks to the database class, we're going to have to update our NotesController to no longer call a fetchAll method. All right, let's go to notes. And yeah, DB query. And do we want to keep this method? Do we like that? fetchAll? Or do we want it to be something different? Like maybe you just want it to be called all.
Or do we want it to be something different? Like maybe you just want it to be called all. Or maybe you want it to be called get. So here's my query. And get me the results. Keep it simple whenever you can. So with that in mind, we're going to stick with get. Come back to database. Here is our method called get. And again, this is just going to say return this statement fetchAll.
Here is our method called get. And again, this is just going to say return this statement fetch all. And again, notice that I now own that method name. Come back. Refresh. And that works as well. So I think this is a pretty cool refactor. So you know what? I get it. We've been sort of in the woods the last couple episodes as we talk about some nitty gritty
