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

Refactoring PDO connection0:00

You know, it's funny. A lot of programming consists of taking code you have that already works, but you don't stop there. You keep iterating on that same code over and over until it doesn't just work, but it's also beautiful and flexible to work with. So with that in mind, if we take a look at the Database class that we whipped up here, are there ways to make it a little more flexible? And I think the answer is yes. Have a look at this DSN here. Notice that I've hardcoded many of the options here, like the host and the port and the username,

And these are the sorts of things we need to think about. So let's do this. In most editors, there will be some way to, for example, command click on a class name, and it takes me directly to that file. And here I can see the constructor for that PDO class. And notice, yes, it wants a DSN, but then we can pass separately from the DSN the database username, password, and options. Okay, so I think that's a pretty good first step. All right, so username in this case is root. Next, the password, because this is local, is simply blank.

Explaining class constants1:28

All right, so username in this case is root. Next, the password, because this is local, is simply blank. But of course, in production, you would have a password. And then finally, the options can be an array. Okay, so if I come back to index.php, you'll remember in the last episode where I noted how annoying it is that I have to pass this constant every time I want to fetch the results. Oh, and by the way, forgive me, there's so much to cover, and sometimes I forget things. I didn't outline what those two colons on the class means. The technical term is scope resolution operator, but you don't need to know that. My guess is if you could pull 50% of working php developers, they would not be able to

The technical term is scope resolution operator, but you don't need to know that. My guess is if you could pull 50% of working php developers, they would not be able to tell you what the name is. And that's totally fine. You just don't need to know it. More important is knowing what it does. So that gives you access to a static or a constant that was defined on the class. Again, there's so much here, you don't have to learn every piece. You can let it wash over you bit by bit. You can think of a constant as nothing more than an identifier for a particular value.

You can let it wash over you bit by bit. You can think of a constant as nothing more than an identifier for a particular value. But most importantly, that value, no matter how many instances of the class you have, will never change. And that's why we call it a constant. It's not an instance property. It's a constant. So yeah, notice this example on the PDO class. It looks like we have all of these numbers that represent different data types. 2, 3, 4, 5.

It looks like we have all of these numbers that represent different data types. 2, 3, 4, 5. Yeah, that's about it. For developers though, the numbers don't mean much to us. It's hard to remember what 4 means, right? Or what is the difference between 2 and 4? So instead, the natural thing to do is attach an identifier to each number. So now I can see param int is 1. data is 0. Oh, that's param null.

Data is 0. Oh, that's param null. And then when I ever need to access that value, or in this case, the number, well, if I switch back, I can say className:: and then the name of the constant. And as a general rule and good practice, we make all constants uppercase to make it crystal clear. This is not an instance property. This is a constant. Okay. Anyways, all of that to say, I can now remove this from the fetchAll call, and let's declare

Setting default fetch mode3:41

Okay. Anyways, all of that to say, I can now remove this from the fetchAll call, and let's declare it as an option when we instantiate the PDO class. And I can do it just like this. The key will be PDO, and this also is a constant, ATTR_DEFAULT_FETCH_MODE, and that will point to PDO::FETCH_ASSOC. Okay, so now that will apply across all results that we retrieve. All right, so now I can remove the username up here. But that still leaves the host and the port and the database name that needs to be dynamic. So what if we had some kind of configuration array?

Building DSN from config4:12

But that still leaves the host and the port and the database name that needs to be dynamic. So what if we had some kind of configuration array? And for example, I could say the host is localhost, the port should be 3306, and the database name should be myapp. Okay, well, if I defined that outside of the DSN, I could then substitute it like this. config('host'), and then config('port'), and then finally, config('database'). But while we're here, why don't we also do the character set? And I'll paste that in, and then once again, update this as well. All right, so this is getting a little messy, but we can clean it up. And here's what we have.

All right, so this is getting a little messy, but we can clean it up. And here's what we have. And I'll hide the sidebar. But next, check this out. I'm going to clean it up a little more. I will call a function named http_build_query that php provides. And yeah, as its name suggests, it's actually intended for building up a query string like this. Example, .com foo equals bar. This is the query string.

And that's pretty much our DSN, isn't it? So why don't we try this out in the browser? And what I'll do is I'm going to pass this whole function call to our dd function, and we'll have a look in the browser. I give it a refresh, and yeah, I mean, that's pretty much what we want. The only remaining thing is this awkward mysql colon section. But what if we just added that at the beginning? We prepend it, mysql colon, and then we concatenate whatever is returned from this function call. So if I come back and give it a refresh, and yeah, that's pretty much our DSN, isn't it? It's exactly it.

Pushing config out of class7:42

the environment, the solution is to push those values upward. All right, so let's do that one step at a time. First step, I'm going to take all of this and push it out of the class. So instead of declaring it inline here, I will accept it like so. config. All right. So now I will go to index.php, paste it in here, and then pass it to our constructor. And now let's just clean that up really quickly. Yeah, notice what I mean. We've pushed it out of the class and upward to the next level where we call or instantiate

Creating a config.php file8:35

And again, you're right. So what's the solution? Push it upward again. What if we extract this into its own file where we have one version of that file for local development and a different version of that file for production? I think that would solve the problem. So let's give that a shot. Create a new file, and I'm just going to call it config.php, and I'll paste that in. But instead of declaring a variable, I'm going to return. Okay, so come along for the ride for just a minute.

But instead of declaring a variable, I'm going to return. Okay, so come along for the ride for just a minute. Now back in index.php, I can say $config equals require config.php. All right, and let's do a sanity check. Does everything still work? And it does. All right, very cool. And even better, we learned something new, haven't we? We've learned that the return keyword is not exclusive to function calls. It can be used within regular files just like this.

We've learned that the return keyword is not exclusive to function calls. It can be used within regular files just like this. And whenever I require this regular file, this is what we return. Okay, so now back in index.php, I'm saying create a variable called config and make it equal to whatever is returned from this required file, which is pretty cool. Okay, so now let's go back to database.php. Are there any remaining values here that should be dynamic dependent upon the environment? And the answer is yes. We are still hard-coding the username and the password. Okay, so we have two ways to solve this.

We are still hard-coding the username and the password. Okay, so we have two ways to solve this. You learned in the last episode you can declare the username and password as part of your DSN connection string. Another option, though, if you want, is you could pass them in separately. So why don't we accept a username and a password if you want to take this route, and then we substitute them here. Now they're dynamic. And that looks good. And if you want, you can even assign default values.

And that looks good. And if you want, you can even assign default values. So you might say set the username to root or default of root because it's so common, and the same for a password being an empty string for local development. All right, so back to Firefox. Give it a refresh, and it still works. But yeah, I think these have been pretty good and sensible refactors. Notice that now, other than this MySQL part, which I'm just going to assume we're always using MySQL in this series, but other than that, everything can be dynamic. And if I ever need to change this, well, maybe port changes to 3309, database changes to

using MySQL in this series, but other than that, everything can be dynamic. And if I ever need to change this, well, maybe port changes to 3309, database changes to something else. Of course, this is going to break when I try it, but it proves that we are now reading from that .env file. Okay, so now let's bring it back. The final thing, remember, this configuration file is not exclusive to your database credentials. You can use it for the entire application. So with that in mind, maybe we should key this, like this. Let's create a key called how about database, and then I will paste all of that in.

So with that in mind, maybe we should key this, like this. Let's create a key called database, and then I will paste all of that in. And that looks pretty good. And now think about it, in the future, if you ever have specific configuration that is not connected to the database, now you have a place to put it. For example, as you mature, you will often work with external services and APIs. And often those companies will give you tokens or secret keys that you need to reference in your code. So for example, at Lerikast, I use a tool called prerender. And maybe they give me a token and a secret key that I need to reference.

So for example, at Lerikast, I use a tool called prerender. And maybe they give me a token and a secret key that I need to reference. Well, again, this would be a good place to declare it. Because remember, those tokens and secrets, again, will often be unique, depending upon whether you're in a local setting or a production setting. Okay, and trust me, you'll learn more about this in the future. So now if I come back to index.php, and now we just need to update this to pass config database. Okay, so sanity check, it still works. I think we're done for this video.

Okay, so sanity check, it still works. I think we're done for this video. But before I let you go, I get it, we covered a lot here, and there were a bunch of new concepts. And sometimes that can be a little overwhelming. So think about it. We talked about taking dynamic data and pushing it upward. You learned about environments, local versus production. You learned how to return and require data from a file. So yeah, a bunch of concepts here.

EnvironmentsPush Configurable Data Upward

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