- Overview
- Transcript
5.2 Interfaces
An interface is basically a contract. It tells you exactly which methods should be present in each class that adheres to that contract. Interfaces are a great tool to help you decouple your classes from the rest of your application. And that’s where the true power of object oriented programming really shines!
1.Welcome1 lesson, 01:07
1.1Welcome01:07
2.The Absolute Basics of OOP5 lessons, 22:53
2.1What Is OOP?04:40
2.2Classes vs Objects05:42
2.3Class Constants and Internal Reference04:19
2.4Public vs Private Scope06:05
2.5Copying vs Cloning Objects02:07
3.Digging a Little Deeper Into OOP5 lessons, 43:52
3.1The Single Responsibility Principle15:18
3.2Magic Methods11:16
3.3Autoloading Through SPL03:37
3.4Working With Namespaces05:14
3.5Autoloading With PSR-008:27
4.OOP inheritance2 lessons, 12:02
4.1Class Inheritance And Protected Scope09:22
4.2Overriding Parent Methods02:40
5.OOP Abstractions5 lessons, 1:00:05
5.1Abstract Classes05:59
5.2Interfaces14:53
5.3Static Properties And Methods06:49
5.4Traits14:44
5.5Dependency Injection17:40
5.2 Interfaces
Hello and welcome back to PHP-OOP Fundamentals. In the previous video we went over abstract classes. Now in this video we'll take a look at interfaces. As we saw before there are certain great benefits to abstracting classes. It's a great way to share reusable code between classes and reusable code is good because it keeps you from creating duplicate code. But we can take abstraction even a step further. Meet interfaces. Now an interface is basically a contract. It tells you exactly which methods should be present in each class that adheres to that contract. But at the same time it doesn't burden you with how the logic in those methods should work. Sounds a little abstract? Don't worry. We'll build a full working example. Say we want to display posts in our Acme app. Well these posts have to be stored somewhere in some kind of a repository. Now that could be any kind of a repository. It could be a database, an RSS feed, or even a PHP array. Ideally our app shouldn't have to worry about where those posts come from or how they are retrieved. The data repository should be like a black box really. Simply input some parameters and it will return a response. The rest of the application hasn't got a clue what goes on inside that black box and this is good because we can change the workings inside of that black box as much as we want. As long as it can input the same parameters and it receives the same type of response, our app won't break, and that's what this contract is for. Okay. Time to get our hands dirty. Let's go inside of the app directory. Now as you will see I've already created a repositories folder and there's already two data files to work with. There's a JSON file and an XTML file. Feel free to copy them from the source code that is included with this course but you can also download them from gethelp.com/joostvanveenn/php-oop-fundame- ntals. Okay and let's just see what these data files contain. First there's posts.JSON. This is just a file containing a JSON object with three items. Item number one has a title and a body and the same goes for item number two and item number three. Then there's another data file called post.xml. It contains an RSS feed of roughly the same post as before. See, here we have our RSS tag, then the channel tag, and then the items one, two, and three and every item contains a title and a description. Okay. So, inside the repositories folder we'll create our data handling classes. First I'll create a file that will contain our contract. Now let's just call that Post.Repository.Interface. Inside here we'll create an interface. Now all our interface will do is specify which methods our app can expect when dealing with a class that implements this very interface. First of all we need to set up a name space and of course that'll be Acme\App\Repositories and then we'll create an interface. Of course that will have the same name as our file. So, that will be Post.Repository.Interface. Now the first method that is in our contract is a public function and that will simply be called All. Now what this will do, it will return all posts as an array of objects and there will be a post title and a post body and just to make sure we remember our pay setting as a dot block. Like so. All right. So, origin post-title and post-body. As you will notice there's no actual body or anything inside of our public function. This is just a contract stating that such a public function should be available. Okay. Next we'll do a public function and let's call that Find and Find will need to take a parameter called ID and this will return a single post. I'll just create a dot block for that as well. Now the parameters should be an integer and of course it should return an object like so. Now of course we could include methods for storing posts and stuff like that but let's just leave it with this for now. Okay. So, now that we have our interface contract ready let's create a class that implements that very interface. That will be a new PHP file and let's call that postjsonrepository.php. First of all I'll give them a namespace as well and that will also be Acme\App\ Repositories and then all we need to do is create a class and let's just call that post json repository as well. I'll clean out this mess here and let's just have that implement the post repository interface like so. Okay and now I'll just open up index.php and as you can see I've cleaned this out quite a bit and what we'll do here is we'll just create a new Acme\App\Repositories and then we need to call post Jason repository like so. And let's just store that in a variable and call that post repository or something. Okay. Right now I'll fire up the browser and now here's what happens if you do not define the methods there are in the contract. See? Our JSON class is required to define the two methods in our interface and as a matter of fact those methods even need to accept the very same parameters as in the contract. Okay? So, the next step is to take these two methods and define them. So, we'll open up our PostJsonRepository and create a public function here called All and then we'll just copy that once and create another one called Find and that would take an ID. So, now our error's gone but of course we still need to code logic into these methods. Let's just do that now. Okay now this file PostJsonRepository. We'll deal with the post.json data file exclusively and in a minute we'll build another implementation of post repository interface that will deal with getting data from the post.xml data file. Here's what we'll do. We'll just create a constructor and set up the path to posts.json. So, that will be in the directory that we're currently in and then the file will be called posts.json. Now we can get the contents of this file by running it through file_get_contents just like so and then we'll just run the contents of that file through json_decode. Now this will decode the JSON inside of the file and if I pass the second parameter true then it will return that as a multi-dimensional array. Okay? And then let's just store this data inside of a post variable and for good measure I'll just define that at the top of the class here. Protected Hosts like so. And maybe we'll make that equal to an MT array. Okay and now what we could do in our All method is just return this-posts like so. Inside of our Find method we also want to return something but we need to do a check first. We'll check to see if we have a this-posts ID key. So, say we pass two here, we're checking to see if we have an item number two here. Well if that's the case then we'll just return that and if not we'll just return an empty array like so. Okay and let's have a look and see what that gets us. We'll just do a quick var.dump here and that will be PostRepository and let's just take the All method for that and I'll just refresh the browser. Pretty close but not quite there yet. You see what we have here is an array of arrays and we want to have an array of objects. So, let's just fix that. Of course we need to be in our post JSON repository and the easiest way to create an array of objects is to just loop through the multi-dimensional array that we just created. So, we'll just foreach posts as post and then we'll just add each post to the thisPost array only what we'll do is cast it as an object. Like so, and now this should give us an array of objects, let's see if that works. And indeed, here we have an array, three items, the first item is an object, and the second item. Is an object as well. Okay, time to neatly wrap our posts in html. Here in the next door PHP I'll just store the result of the old method inside of a variable called posts, and then we'll just echo an ordered list just like so, and make sure we clean this up so that we have a beginning, and an end tag. Now I'll just rename this to posts. And I'll look through it. Foreach posts as post, we'll just echo a list item, and then let's just display the post title there. So, post title, like so. Now, let's see if we can also display a single post. We'll just do post equals post repository, find, and I think we'll be looking for post number two. And then we'll just neatly wrap that within an H1 tag, like so. Post title and then maybe we'll wrap inside of a paragraph tag the post body like so. So, let's fire up our browser and see if that's worked. Well, we are getting three posts here. But here instead of displaying the second post, we're displaying the third post. So, probably did something wrong in post Jason repository there. Yes, I started with a new array. And of course I should pass the key here. So, for each post as key post. And there we are. Now when we pass two we get the second post indeed. Okay, so we've got our posts.json repository ready. Now, our boss tells us he wants our app to display items for an RSS feed, Rather than a JSON file. In our case, because we have so much of the groundwork laid out, that's easy. First of all, I'll just copy our post JSON repository class and we'll just call that post RSS repository like so. And now all we have to do is open up this class and change the internal workings of our All and Find methods, but first we'll change the class name, like so. OKay? Now inside of our constructor, we'll still need a loader file, only we'll have the XML extension and instead of running it through JSON Decode and file get contents We'll do simple XML, and then load file. Okay? Like so. Need to make sure this actually says XML. And we can lose this second argument cuz we won't need it in an XML load file. Okay? And that should do. Now, let's rename this to something a little more appropriate. Maybe XML. And now our XML variable will hold a simple XML element. Now the fun this with XML elements or simple XML elements is that you can query them using Xpath. So let's do so. Okay, so what kind of path do we need to use? Let's open up our XML file again. Here we have a channel path and it's children items. So that's what we'll query forward. Channel/item And let's just save that in a variable called post. And like before we can loop through each post as key post. Only this will have to change just a little bit. These post items that we have here are simple XML objects and we need regular objects. Let's just make sure that we get those. We'll just take a post. And run it through json.encode. Now, this will take the simple XML object and turn it into a JSON object. And then all we have to do is run it through json.decode again to get a normal PHP standard class. And then we'll take that class and use it to overwrite the POST variable. Now, there's something else that we need to do because we are expecting a post body, right? Well if you have a look at the post XML, we have a post description. Okay, so we need to set a post body, and make that equal to post description. And then once we've done that, we can simply unset($post->description) like so, and our $post object's ready. And now all we have to do is make sure that we add it to the $this->post[] array. For that, we'll just take $key+ 1, and then that will be equal to our $post object. So just a quick recap. We're loading in the XML data. Loop through it, then create a post object and add the post object to our thispost array. Now that again leaves us with an array of objects much like in the post JSON repository so I'm guessing we will not have to change a single thing. In these two methods here, okay. Let's go back to index.php and swap out PostJsonRepository with PostRssRepository. Now if our repositories are truly decoupled then swapping these two out should leave us with exactly the same results as before. Let's have a look. And yes, they have that's exactly the same data. Only, from XML. And that's great just as long as we stick to our interface, we can swap out repositories like there's no tomorrow. The ability to have completely implementations of exactly the same functionality is called polymorphism. Now we could create a bunch of other repositories as well. We could for instance create a post database repository. And that could work something like this, we could for instance inject the database here. Or get it from the other class. So, we have a database, then fetch all posts here. And fetch a single post here and return in. And what's more, because their truly interchangeable, we could even use these three classes next to each other. No problem. To wrap things up, interfaces are a great tool to help you decouple your classes from the rest of your application, and that's where the true power of object oriented programming really shines. Bear in mind, however, as of now there is no native feature in PHP to require a certain type of output. Now maybe that could be a future addition to the PHP core, but for now, I have defined the expected results in a doc block in our interface. This is something to really watch out for because a class can only truly be coupled if both input and output are equal between different implementations. Ok, that's all for interfaces. I'll see you in the next video.







