Migrating Model Logic0:00
Now think about it, whenever you're building a traditional server-side application, you can of course improve readability by simply adding a method to a class. So for example, on my User model, if I need to determine if the current User follows another User, then I might write something like this. Now anywhere in my codebase I can say, does the current User follow that other User? And it reads better, and it allows for better encapsulation, better testability, a bunch of things. So the question is, how do we migrate functionality like this over to the client side? Well, you have a couple options. Of course you could visit your API resource, and I could include an array of all of the
Well, you have a couple options. Of course you could visit your API resource, and I could include an array of all of the Users that the current User follows. So I don't have any kind of relationship here, but if I did, it might be something like this, where you pluck an array of IDs that the current User follows. But yeah, that only gets us half of the way there, doesn't it? In your client side, in a view component or something like that, you'd have a User, and yeah, you could call .follows, but that's not returning a Boolean, that's simply returning an array of the IDs that you follow. So yeah, if we want something like this, well of course we will need to create an object.
Accessing Inertia User1:15
an array of the IDs that you follow. So yeah, if we want something like this, well of course we will need to create an object on the client side, and you'll often find yourself doing this. So let's talk about it. Let's begin, let's go into any random page. Let's go into user/index. So this page corresponds to this list of Users that you see in our little demo CMS here. So why don't we play around first by...we'll do it right down here. I'm using the composition API, so we'll say when the component is mounted, and real quick, I had to import that at the top, as you see here from Vue.
I'm using the composition API, so we'll say when the component is mounted, and real quick, I had to import that at the top, as you see here from view. Okay, so when the component is mounted, let's console.log the currently signed in user object. Now if you've worked with Inertia before, then you very likely have something like this in your main handleInertiaRequests middleware. You'll see it right here. We are sharing the currently authenticated user. And right now, it simply includes the username, but in your case, it would surely include a lot more. Okay, so if I want to grab that using the composition API, it's a little different,
a lot more. Okay, so if I want to grab that using the composition API, it's a little different, of course, because if you have the options API, you might do something like this. page, props, auth, user, username, right? But in this case, this would be undefined in the composition API. So instead, all you have to do is import Inertia, and then you can access it basically like this. All right, let's give it a shot. Inertia.page.props.auth.user. And actually, you know what, before we even get there, let's just see what the page object looks like.
And actually, you know what, before we even get there, let's just see what the page object looks like. Okay, so I have my watcher running behind the scenes. And oh, I'm so sorry. Let's go back to our User resource and get rid of that. Okay, so if we have a look at the console, sure enough, here is the current page object. And you'll see here's the props, there's the authenticated user, and this is what we want right here. Okay, let's come on back. And I can say props.auth.user.
Creating Client User Class3:19
Okay, let's come on back. And I can say props.auth.user. And now I have my user object right here. But now I don't want a basic object here. I'd like to add some behavior and logic to it. So one thing we might do is create a dedicated class. Let's do that now. Now, we could create some People create a core directory, some people throw all of this stuff in services, some will create a models directory, do whatever you want. To be honest, I've done all three of those at some point or another.
stuff in services, some will create a models directory, do whatever you want. To be honest, I've done all three of those at some point or another. So let's add a directory here and I'll call it models. And keep in mind, even though I'm calling it models, in real life, I'm probably not creating a model for every object in my system. So I'm not creating a parallel of my Eloquent models, because often it's just not needed. I would only reach for this approach in situations where I do interact with an object quite a bit. And this will often be your User object, it will often be the object that represents the core thing in your application.
And this will often be your User object, it will often be the object that represents the core thing in your application. So for example, for a Laracasts, it might be a Video or a Series, these core things for your application, I would use. But no, I'm not creating a model class that parallels every Eloquent model on my server side. Okay, so let's add a new model, quote unquote, called user.js. And this will be a class. And now when I instantiate this User, we will give it the attributes that we reviewed just a moment ago.
And now when I instantiate this User, we will give it the attributes that we reviewed just a moment ago. And if I want those attributes to then be available on any instance of User, I could always use Object.assign. So assign these attributes to the current object, all right, and we'll export this. Okay, let's leave it like that for now and switch back. Now I will import User from models/user. And if we scroll on down, let's now create our User, pass through the User object, and then log that new User instance to the console. All right, back to Firefox, give it a refresh, have a look.
Adding User Methods5:18
then log that new User instance to the console. All right, back to Firefox, give it a refresh, have a look. And now you'll see it looks like what we had before, but now we've wrapped it up in our own client-side User class, which means here I can add any behavior that I want. Let's add that follows method again. We'll accept another User. And again, you'll perform whatever check you need to. Maybe if we had that follows property, you might do something like includes user.id. I don't know, it just depends on how you wrote it. In our case, why don't we force it to true?
I don't know, it just depends on how you wrote it. In our case, why don't we force it to true? Now we could work with it. So let's say let user, like so. And I could say console.log user.follows some other user. And it doesn't have to be an instance of User, it could just be an object that has, you know, we could duct type. It could be an object that has whatever properties we need to verify against. So if we run this, we should get true. And we do.
So if we run this, we should get true. And we do. You might ask what their subscription plan level is, or maybe you have a plan label that gives you the name of their plan. You know, little things like that can often be really useful. You could even add little helpers, like check to see, often if you're iterating over a list of users, you want to check, is that user in this iteration the current user who is signed in? So you might add a method called is. Same thing.
So you might add a method called is. Same thing. And again, you might do something like check if the current user's ID equals the ID of the User that you're verifying against. And let's make that triple equals. All right, so now when we wrap this up, yeah, you could say, well, is the current user this other User? And of course, that reads much better than constantly having to say, does the user ID equal the other User's ID? Now we've wrapped it up and added it as a method on our User object or class.
equal the other user's ID? Now we've wrapped it up and added it as a method on our User object or class. And you know, other things like, let me think, I think for Laracasts, I have something like hasPrivateProfile. That can be useful. Your profile on the site could be public, or you can mark it as private, in which case nobody can see it. That might be something I want to check against. Sometimes I have special affordances if you are a lifetime User on the site. So we might have something like that.
Sharing Current User8:07
It would be nice if every component just had access to the current User. So you have a couple ways to make this work. Because I'm using the composition API here, I can't easily use mixins. So one option would be you could migrate this over to the options API, and then you could create a global mixin. That would take the form of something like where you initialize your app, right here where you create the view app, you could do something like add a mixin and then give it a path to your global mixins class or objects or module that you import. That would be an option. But yeah, if you're using the composition API, you're not really supposed to do that.
Creating useCurrentUser Composable8:42
That would be an option. But yeah, if you're using the composition API, you're not really supposed to do that. I don't even know if there's a way to do it. So instead, we could reference the previous episode where we talked about composables. That would be fine as well. Let's see what that might look like. In my composables directory, let's add a new one, and we'll call it useCurrentUser. That would be fine. So again, we're going to export a function with the same name. And yeah, it'll basically be what we did here.
So again, we're going to export a function with the same name. And yeah, it'll basically be what we did here. Let's grab that line, switch it over, import it. And notice PHPStorm automatically imports the dependencies, and then I could return it. So yeah, even for basic little things like this, that's an option. Or if you want to expand this file to make it a little more generic, where it could return a number of things, that would be fine too. So let's see if we can use this. Come back to my component.
So let's see if we can use this. Come back to my component. So let's see, we can get rid of that, and then we're no longer importing the User model. We will instead import useCurrentUser. All right, give that a reformat. And yeah, now when the component mounts, let's console.log useCurrentUser, and let's have a look. Give this a refresh, and there's our object again. So let's try to interact with it. We had isALifer.
So let's try to interact with it. We had isALifer. Why don't we hard code that to false and see if it works. Give it a refresh, and it should say false, and it's working. So yeah, what you might end up doing is you could have $currentUser equals useCurrentUser, and then wherever you need to, you could interact with it. currentUser.isALifer, do they follow someone? Are they somebody specifically? Do they have a private profile?
mixin. Generally with mixins, you want to be somewhat thoughtful because they are then available to every single component in your system. So you don't want to go overboard, but something like a currentUser mixin property, I think would be perfectly fine and useful in most apps. Otherwise, make it a composable, and then import it when and where you need to.
