Join Kevin Skoglund for an in-depth discussion in this video Solution: The bicycle class, part of PHP: Object-Oriented Programming.
(digitized jingle) - [Instructor] I hope that you were able to complete the challenge and write your bicycle class with the requirements that we talked about. Even if you feel confident that you got the right answer. Following along with me to make sure that your solution matches mine. The first thing that I did was I created a new file inside this classes directory called bicycle.class.php. That's a common standard to name it singular just like the class name, and to put .class.php. Then inside that file, I put my php tags and I defined a class for Bicycle, capital B, singular.
Then inside of there, I put in my properties. I have brand, model, year, category, color, description, gender, and price. I also have protected properties for weight_kg and condition_id. We'll come back to those in minute. I also knew that I needed some constants, so I have class constants for categories and genders and I made those public. The idea being, that we might want to be able to access those from some .php code somewhere else. I also have a constant for condition options. We'll come back to that in a moment.
Then once I had my properties, I defined my construct method. That's __construct and it's got to be public. I'm going to just take in one argument which is an array of arguments. I could list all of these out but that's quite a long list, so rather than have all of those arguments listed and have to worry about the order that they come in, I'm going to use this common design pattern, where we just pass in an array of arguments. Now for each one of my properties, I'm going to check in and see if we were passed in an argument for it and if so, we'll use it. If not, it'll default to some other string.
I'm using .php Seven's null coalesce operator to do that. I also just want to show you, this is what it would look like if we were using the old style ternary operator. We just check to see if it is set and if it is set we use it, otherwise we have a default value. They do exactly the same thing. This is a newer and I think slightly cleaner way to do it. Notice that I don't have any default values set on any of these. I could, but I've chosen to put those into the construct method. So if price is not set, it'll go to zero. If kilograms is not set it'll set to 0.0 and so on.
I also just wanted to mention another thing to you, is which is that it's a common pattern to set your arguments like this. For each of the arguments that we've been passed in, use each one as a key and a value, K and V. If the property K exists on this instance, then set that key equal to V. Notice here that I do have a dollar sign in front of K, because this is a dynamic variable. It's not a single property called K, it's dynamically going to be something different. It's brand, it's model, it's year and so on.
But I'm going to set each one equal to its value. This is a common way to do it. It's a very easy way to say, you know what, whatever arguments were there, just take 'em and put 'em in the properties if they exist. Right, then I can avoid having to do all of this code from line 30 to 39. There's one big drawback to doing it this way though, which is that it means that any private and protected properties could be set. That may not be a big deal to you, but just keep that in mind, because in this case, we're always going to have access from the construct method to those private properties.
So even if we didn't want our construct method to have access to it, it will. So just keep that in mind. But I wanted to show you that, because that is a common technique that people use for populating their properties. Okay so once I had my construct method written, then I know I'm able to create instances and to populate those properties. The next part of our challenge was to do weight in kilograms. We already did this exercise in previous chapters. You can refer back to the old code if you want. You can also pause the movie if want to just compare yours, but we have a method that allows us to set the weight in kilograms.
We have one that allows us to read that value back. And we have one that'll allow us to set it in pounds and one that allows us to read that back. That code is exactly like what we had previously. Then for condition, all right if we go back up here, we have a protected property for condition_id and then we have condition options. This another constant. Both of these are protected, because the outside world doesn't need to have access to those. We're going to use it though, because we're going to store this id, rating basically the condition of a bike on a scale of one to five.
And then we're going to use that to say what the string is that goes with that. So if someone calls this method condition here, then it should be able to return that value. And so we do that by using that class constant with self:: in front of it and since it's an array, an associative array, we can ask for its key. So the key is the number that we've stored in condition_id. So we use that, pass it in, and it should return back one of those strings to us. If the condition_id wasn't set, it's not greater than zero, then it would just simply be unknown.
So with that, we completed our definition for our bicycle class. We're going to worry about using that in the next movie. For now, we need to make sure that we load it up and we have access to that code. So we also need to go into initialize.php and make sure that the class is available. There are a couple of different ways we can do that. We could simply require once, each of the files that we want. That's nice, because it allows us to control the order that they get loaded in, if that matters. If we don't really care about that and we just want to load all of the classes that are in that directory and it's okay to load them in alphabetical order, we can simply use glob and pass in that directory.
I'm using a pattern here with this wildcard character and I'm saying grab all of the files that are in that directory that have .class.php at the end of them. And for each one of them, loop through and require it. So this is a common pattern to just basically say, grab all the files in the class directory and require them, so they're all available. Another technique that we can use, either instead of that or in addition to it is to define my_autoload. So we write a function. We give it any name that we want. Then we take the name of that function, then we pass it in as an argument to spl_autoload_register.
And then PHP knows that this is one of the places that it can look for our code. Now if I've done my job properly by loading them manually, either individually or by loading all classes in a directory this shouldn't come up, but it's still a good practice to have autoload in there as well. So now that we have our bicycle class and it's being loaded up as soon as our page, Bicycles.php calls initialize.php now it's available for us to use on this .php page.
- Defining classes
- Calling methods
- Class inheritance
- Extending and overriding classes
- Accessing and controlling access to properties and methods
- Static properties and methods
- Magic methods: constructor, destructor, and clone
- Creating a PHP OOP project