Caching Architecture Options0:00
Now, before we move on to discussing PubSub with Redis, I do think we should talk a little bit about architecture, or at least organization, when it comes to our caching here. So right now, I honestly think this is fine. We fetch all articles and we wrap them within a cache call. And we know that behind the scenes now, we're going to use the Redis driver. However, it could be possible that you will need to perform this query in multiple parts of your application. So you could end up in the situation where you're copying, pasting this, or even rewriting it from scratch. And if you do that, the potential for the cache keys to not line up or the length to be different, it just grows and grows. And worse, yeah, I mean, this is not overly fun to write. It's kind of annoying. So let's review maybe two or three different options that you might consider to clean things up. First, we could definitely reference like a repository. And you know what,
Extracting Articles Repository0:44
It's kind of annoying. So let's review maybe two or three different options that you might consider to clean things up. First, we could definitely reference like a repository. And you know what, I think in our community, they may be inappropriately get a bad rep. And I don't think they deserve that. And in fact, there's no need for you to even call it a repository. For example, maybe we could just create a class called Articles. And that's good for me. So if I want to fetch all Articles, as a first step, I could just take this and put it within here. So we're taking this code that we might have needed to repeat across multiple controllers or routes, and we're just throwing it into a class and giving it a name. Right? Very simple. So now, should you need to fetch all Articles, you won't reference Eloquent directly, you would just do something like this. So let's go to redis-cli, delete LaravelArticles.all.
So now, should you need to fetch all articles, you won't reference Eloquent directly, you would just do something like this. So let's go to Redis CLI, delete LaravelArticles.all. Okay, let's go to Chrome, give it a refresh. That should now be cached, right? And it is. So now for subsequent requests, of course, we're pulling from the cache rather than performing the database query. And further, if you do need to perform this query from another controller, yeah, you do the same thing. So all we did was extract this bit of code into a reusable class. You can call it a repository if you want. That's kind of what it is. But you know what, who cares? Just call it articles. That's what I'd recommend. Next, though, even though I would say this is perfectly fine, I have no problems with this whatsoever. And it might actually be what I would end up doing personally. But it's possible you want to take it a step further. Maybe you
Adding a Cache Decorator2:16
this is perfectly fine, I have no problems with this whatsoever. And it might actually be what I would end up doing personally. But it's possible you want to take it a step further. Maybe you want to inject things. Maybe you want to perform the caching as a decorator. And that way, you can turn on and off the caching aspect. Okay, well, if that's the case, we would get rid of this entirely and just perform the query. And then you might add another class. And once again, it's called a decorator, but you don't need to throw decorator into the class name if you don't want to. I might just do something like this, CacheableArticles. Now, the way a decorator works is you instantiate it, and you give it an instance of the class to which it's decorating. And this will accept articles, which I will assign. Okay, so articles would be an instance of this class. So now if we're going to decorate it, we just mimic the API. In this case, all we have is the
will accept articles, which I will assign. Okay, so articles would be an instance of this class. So now if we're going to decorate it, we just mimic the API. In this case, all we have is the all method, we delegate. So I could say this articles all. So we delegate to the original implementation. And then we decorate it in some way. And in this case, we might do what we had before, something like this. And we don't need to save that we can just return it. Okay, so does that make sense? We knew up cacheable articles. As the constructor, we give it an instance of the class to which we are decorating. And then we mimic the API, we delegate to the original implementation. And then we decorate it however we need to. In this case, we decorate it by wrapping it within a caching layer. So now articles can remain very, very simple. But then should we need to enable or turn on caching, we would use this decorator here. Okay, so now
wrapping it within a caching layer. So now articles can remain very, very simple. But then should we need to enable or turn on caching, we would use this decorator here. Okay, so now that would take the shape of something like this CacheableArticles. And let's do this. Well, actually, I'm going to show you this in two steps. First, we could say articles is new CacheableArticles. And then we give it a new instance of our regular repository. And then we could say return articles all. So think about it, what's going to happen there? Well, we call this method, let's assume we don't have anything in the cache. And in fact, I'll delete that. Okay, that means it's going to delegate to articles all here, we perform the query, and then we cache it. And then on the next page request, per usual, it's already cached. So we would never even refer to this method here. Alright, let's try it out. Give it a refresh, that should now be cached.
Binding Decorator in Container4:45
And then on the next page request, per usual, it's already cached. So we would never even refer to this method here. Alright, let's try it out. Give it a refresh, that should now be cached. And it is. So from now on, yeah, it's almost like we never even called this method. As you can see there. Cool. So another thing you might do, if you don't want to constantly reference this, what we could do is bind to this into the service container. So for example, I could say bind to the key articles. And what I want that to return is a new instance of this. So just return my decorator. And that way, if I do want to change this or modify it, or decorate it in some other way, I would only have to update one location here. Okay, so the way this would technically work is something like this. If we tried to resolve articles out of the container, or you could also do app make. So like, let's die and dump that.
so the way this would technically work is something like this. If we tried to resolve articles out of the container, or you could also do app make. So like, let's dd that and view it in Chrome, you'll see that we get an instance of cacheable articles. And like I said, this is the exact same thing as saying resolve. That's new in Laravel 5.3. I think it's just kind of a more readable name. But we'll get the same thing. Anyways, that's fine. But if we want to type hint it, well, let's see what happens. I think this is going to fail. So I give it a refresh. And yes. So what's happening here is we are type hinting an instance of articles. And Laravel is in fact detecting that and it's returning this. But what it returns is not an instance of articles. It's an instance of cacheable articles. So if we do want to take advantage of the the automatic injection here that Laravel provides, in this case, you would need to use
Using Interfaces for Injection6:19
of articles. It's an instance of cacheable articles. So if we do want to take advantage of the automatic injection here that Laravel provides, in this case, you would need to use something like an interface. So you might say implements Articles. And then we would need to update this. Maybe this is like our eloquent implementation. Just bear with me here. So then this could implement the same thing. And for larger projects, this can actually be pretty useful, I would say. That way you can ensure that these two are constantly in sync. Okay. And then you would have your interface here. And this would be where we define it. So our contract is just that we have an all method. This implements it. This implements it. And now our key that we bind into the container is an interface. The thing that we are type hinting here is not a concrete class. It's just an interface. And this conforms to that interface. So it should all work like we expect.
