Why Wrap API Responses0:00
You may find in your projects that when you perform API calls, the result or the response that you get doesn't match the format or the flexibility that you would want for your code. So what you end up doing is you perform the API query. I'm going to show you a little example I have here, by the way. You perform your API query, but then, yeah, for anything that doesn't fit the format you want, you kind of litter your templates a bit more than you would like. So in this case, we're fetching a podcast feed, and we filter through it. And then for each item, well, I do want the duration, but they return it in seconds, but I want it formatted as minutes. And then maybe also the sharing URL, well, I need to modify that a bit. But all I have is an array here. It's not an object, so I don't have any methods I can call, and it just gets a little bit messy. So in these sorts of situations, a really good technique is to simply wrap it up. Very simple.
Mapping Feed to Objects0:46
object, so I don't have any methods I can call, and it just gets a little bit messy. So in these sorts of situations, a really good technique is to simply wrap it up. Very simple. So we're going to go to this PodcastController I have, and don't worry, it's very, very simple. In the index method, we fetch the feed. Fetching the feed simply makes an API call to simplecast.com. It caches it, and then it returns the JSON response. So the response will look something like this. Let's open up Chrome, give it a refresh, and this is what we get. Okay? So for each item, think of this as a single podcast. And in the view, we're just referencing these. But now I want more control, so I'm going to wrap it up. And we do that very, very simply. Down here, before we return, I could just save this to feed. Next, I can map over it using array_map, or sometimes it's just as easy to use Laravel's collect function,
very simply. Down here, before we return, I could just save this to feed. Next, I can map over it using array_map, or sometimes it's just as easy to use Laravel's collect function, and that will wrap it within an Illuminate collection. A lot of people will bring up performance. You know what? You just don't need to worry about that unless you're at a really, really high level. Anyways, collect that into a nice collection object, and then we're going to map over it. And for each podcast, yeah, I don't want what they gave us. I want to wrap it up. So I'm going to return a new Podcast and then simply pass in that array through the constructor. Now I can return that. Okay, so what have we done here? We've taken an array of objects, and we've converted it into a collection of Podcast objects. So now if we do need to massage the data that was returned, so for example, if any of these need to be massaged,
Creating the Podcast Class2:20
and we've converted it into a collection of Podcast objects. So now if we do need to massage the data that was returned, so for example, if any of these need to be massaged, yeah, we can just delegate to a method on the Podcast object, and that'll keep things quite a bit cleaner. This is a technique I use all of the time. For example, with Stripe and Laracasts, when I fetch Stripe invoices, they're not in the format I want. So I instead wrap them up into my own Invoice object, and that way, once again, I can massage the data or change it or tweak it or format it however I need to. Okay, let's create a Podcast. So I will say we're not creating a Podcast, but we're creating the class for it. And through the constructor, it's going to accept the podcastItem or however we want to refer to that. So now this is going to be equal to this. So now think about it. Let's say the duration, like I showed you earlier,
Moving Formatting Into Methods3:08
the podcast item or however we want to refer to that. So now this is going to be equal to this. So now think about it. Let's say the duration, like I showed you earlier, the duration right now, yeah, we're running it through gmdate, and that will give us something like the time will be 05.15 rather than 60 times 5 plus 15, you know, because it's formatted in seconds. So rather than doing this here, which I don't think is terrible, I think it's fine if you're only ever going to reference it there, but if you instead want to do this, you could say podcastDuration, and now we're calling a method on this. And we can simply return this itemDuration. Okay, so now we're delegating, but things are going to fail at this point. So if I give that a refresh, whoops, let's go back and get rid of that. Give it a refresh, it's going to fail. But in this case, not the right reason. It's failing because
Fixing Wrapper Integration Errors4:02
So if I give that a refresh, whoops, let's go back and get rid of that. Give it a refresh, it's going to fail. But in this case, not the right reason. It's failing because we had to clear the cache. Okay, refresh. Okay, now it's going to fail for a different reason. But again, not the damn reason I want. We're going to import Podcast. And then over here, let's make sure that we namespace it. Okay, so now if we switch back, there we go. This is the error I wanted, undefined property number. So the thing is, when we switched over to using this Podcast class, well, now it's trying to call a title property on Podcast, and that doesn't exist. So one thing, what you could do is just wrap up all of these. And that can be especially useful if you kind of want to block access to some of the things that the API returns. So if you don't want to give members of your team access to this field or
Encapsulating URL Logic6:23
is it podcastEpisodes, or is it podcastID, and then episode, you know, like you always have to go back to your routes file to find it. So this little technique that I've personally been using a lot lately, a lot of people don't like it, but I think, you know what, who cares, and it makes it easier to use. I will change this to something like podcastPath. So give me the path to this specific podcast. And now all of the logic for the URL to the podcast can be stored in one location. And if later, somewhere else in my system, I need to link to that, I don't have to go back to my routes file. I just call podcastPath, and I don't even think about it. Now, this object can access all of its own data to build the URL. And if your thinking is, an object shouldn't know anything about a URL, I don't really think about it like that. I think of it as, it just knows it can return a string that will be used somewhere else. That's it. It's no different than anything like this.
then totally do it. Just wrap it up in your own object, and you're good to go.
