Intro to Blade directives0:00
From time to time, you may find that you need a custom Blade directive. And luckily, it's not too hard once you understand the basic workflow. Let me show you. I have a fresh install of Laravel here, so let's go to the welcome page that's included. And we can get rid of some of this stuff. Let's get rid of all that and this. Okay, so let's review a couple examples. We'll begin with the generic hello world. So, when I say directive, I mean things like this. If, or unless, or section, those are directives.
So, when I say directive, I mean things like this. If, or unless, or section, those are directives. And you can create your own custom ones if it helps your workflow. As an example, when Laravel recently, at least at the time of this recording, added the gate functionality, where you can authorize and limit users' access, they added a new can and cannot directive. And you can do the exact same thing for your own projects. Okay, so first, dummy example. We have a hello directive that we just want to spit out hello world. We can register new directives by going to app/Providers/AppServiceProvider.php.
Registering a custom directive0:53
We have a hello directive that we just want to spit out hello world. We can register new directives by going to app/providers, AppServiceProvider. And now within the boot method, that's a good place to do this. I can say Blade::directive, and now however I want to refer to this, for example, if it's section, then the name of the directive is section. In our case, it's hello. Next, it'll receive an expression, but we're not passing anything through, so I can leave that off. And for that reason, if I switch back real quick, yeah, you could do this if you want, or you can leave it off.
And for that reason, if I switch back real quick, yeah, you could do this if you want, or you can leave it off. Okay, so if we come back, well, yeah, you could do this, and this will work in this example, hello world. So let's go to the top, use Blade, and next we'll boot up a server, and check it out. And sure enough, there we go. We get hello world. But in real life, you probably won't be returning strings. You're actually going to return a bit of PHP, because remember,
View caching and clearing1:44
But in real life, you probably won't be returning strings. You're actually going to return a bit of php, because remember, ultimately this all gets compiled down. So for example, we could just as easily do this, php, and echo out this string. Now if I were to come back and give it a refresh, we'll see the same thing, but on that note, if I were to say hello universe, and if we give this a refresh, yeah, notice how it doesn't update, and that's because Laravel will cache the views. So because nothing has changed in the view side, it doesn't clear.
and that's because Laravel will cache the views. So because nothing has changed in the view side, it doesn't clear. You can do that manually if I open a new tab by saying php artisan view:clear, and that's good to know for development. Anyways, if I give that a refresh, now it works. So if I were to switch back to our welcome.blade.php view, we can now pass an argument. For example, hello world. But this is something that trips people up. Behind the scenes, Blade is just using basic regular expressions here,
Passing arguments safely2:37
But this is something that trips people up. Behind the scenes, Blade is just using basic regular expressions here, so it's not really like you're calling a function. For example, if I were to come back, we're now receiving. Well, at this point, we just think we're receiving like the noun, right? But we're really not. If I were to dd that, let's php artisan cache:clear, and now if I switch to Chrome and refresh, yeah, notice it's not the string world. It's this full captured block right here, including the parentheses.
yeah, notice it's not the string world. It's this full captured block right here, including the parentheses. There are a couple ways we can handle this. In the situation where you're only passing a string, well, you could include that with your echo. For example, we could change this and say hello, and then let's not call it noun because it's really the expression that just happens to include the noun. Finally, if I save this, I bet it'll squawk, and that's just because I need to change our surrounding quotes to doubles,
Finally, if I save this, I bet it'll squawk, and that's just because I need to change our surrounding quotes to doubles, and we'll switch these to singles. Yeah, there we go. Okay, so once again, let's clear our cache, go back to Chrome, give it a refresh, and now we're passing in any argument we want. And by the way, if you're curious what that looks like, let's go into the storage directory, into framework, views, and ultimately this is what gets compiled down.
Working with objects via with()3:42
let's go into the storage directory, into framework, views, and ultimately this is what gets compiled down. Let's review another example. What about, if we go back to our welcome view, what if you want to pass through an object? So let's try this. Let me go to my routes file, and let's say $user will be equal to, let's just find a User, app\User first. I have a test User in this demo application. Okay, so now if we were to switch back,
I have a test User in this demo application. Okay, so now if we were to switch back, maybe we want a directive that will show, I don't know, when the object was last updated, and we want to format it in a very readable way, so something like five minutes ago. Keep in mind, this is kind of silly. It's just to give you an idea of what you can do. So maybe we have a directive called ago, and now you're just going to pass in the object, in this case user.
So maybe we have a directive called ago, and now you're just going to pass in the object, in this case user. So let's go back to our service provider. We now have a directive called ago, and once again I'm going to dd the expression so you can see what we are working with here. So let's go ahead and run php artisan view:clear, and if we go back to Chrome and give this a refresh, yeah, once again you're not getting your object, you're getting a string,
yeah, once again you're not getting your object, you're getting a string, and that's because, again, Blade is using regular expressions here. It's a little bit unique compared to how you normally call a function or a method. So in this case, yeah, it would be nice if I can just translate that into the User object itself. Here's how. If I switch back, Laravel includes a little helper function called with, and it's kind of weird if you don't understand why it's there.
If I switch back, Laravel includes a little helper function called with, and it's kind of weird if you don't understand why it's there. This function, well, in fact, let me just hunt it down for you. Let's see. If we go to with, yeah, it's a little weird, right? It accepts an object and it just returns it. So what this is useful for is chaining, but also for our Blade directives, this is a way we can kind of coerce a string into an object. I'll show you.
this is a way we can kind of coerce a string into an object. I'll show you. If we were to return php, but in fact we do want to echo out the result, so I can make a call to the with function and pass through the expression here. So if you've ever seen this in Laravel, now you understand it. So if expression is equal to something like this, well, when we compile it, this is what we're going to get, a simple call to the with function. We pass through the User object, and that just returns it right back.
a simple call to the with function. We pass through the user object, and that just returns it right back. So now we essentially have a user object that we can chain, and we can say something like updatedAt, and that's a Carbon instance, so we could do diffForHumans, and that would work. Okay. Let's clean this up like so, and I will close out php. And once again, it's squawking. I need to replace that with double quotes so I can nest the variable.
Complex directives with classes6:23
And once again, it's squawking. I need to replace that with double quotes so I can nest the $variable. Anyways, let's try it out. If I come back to Chrome, I refresh, we get 9 minutes to go. Now, another thing you could do if you want, if you have a lot of logic going on and you don't really want to store it here, remember, just create a class, and then you can call it. As an example, something that I'm personally toying around with right now is a cache directive. So this takes advantage of, you might be familiar with it,
is a cache directive. So this takes advantage of, you might be familiar with it, called Russian doll caching. That's just a way to do nested layers of caching. So if you have to invalidate one item, it won't affect the cached state of the other items in the list. Anyways, you don't really need to know about it. But one thing I'm toying around with is adding a cache directive where I could pass in, maybe we have something like a note card, and then I can say endcache.
where I could pass in, maybe we have something like a NoteCard, and then I can say endCache. Now you would display the card however you want, and this content and any database queries you perform in here will automatically be cached. So on future page requests, yeah, you would reduce the number of SQL queries, and also the HTML that you've built up itself will be cached as well. Now the basic way I would do that is here, yeah, I can just reference a different class. So I could even do something like, if it's called RussianDollCaching,
yeah, I can just reference a different class. So I could even do something like, if it's called Russian doll caching, maybe I could call a setup method there, and then once again pass through the expression like that. Now, yeah, in your view, that would just compile down to a setup call with whatever card you're trying to cache. Now, that class alone can be responsible for clearing the cache or putting to the cache or what have you. So now, yeah, you would have that. You'd have something like cache,
So now, yeah, you would have that. You'd have something like cache, and then you would have to do one more for the end cache, and that would take care of any cleanup that you need to do. So yeah, that's really all there is to it. What you're going to find is you probably won't reach for these too often. I've been using Laravel for a number of years, and I think I've created one or two that I actively use. So like in our example of the @ago directive, I just wouldn't bother with that.
So like in our example of the ago directive, I just wouldn't bother with that. I would either use a custom getter or I would just call format directly within the view. It doesn't matter. But anyways, when you need it, this is useful.
