تماشای این درس نیاز به اشتراک حرفه‌ای دارد.

Bring Data In-House0:00

Alright, we've got the UI working inside our app, but technically the puppies data is coming from an external API. That API happens to be a Laravel app, but this is still an external app that we are hitting with an API call with fetch. Uh, and so what we want to do is take ownership of this puppy data directly inside our monolith, our React Laravel Inertia setup. So let's do that in this video.

Review Current Fetch Setup0:21

our React Laravel Inertia setup. So let's do that in this video. Okay, so inside the Laravel app, in the resources/js folder, we've got the queries that we brought over from the original app. Here is how we currently are getting the puppies data into our application. So we hit this API endpoint with a fetch request, which is an async function. And then we get the data

which is a async function. And then we get the data and on the front end, if I open the welcome.tsx page, you can see that we have this Suspense component here, which is going to show a loading spinner until we can get that data that will be displayed in the main component. So if I check this main component, you can see that here we are calling this getPuppies function that we just looked at using the use function from React. And then once this resolves, we are setting it

that we just looked at using the use function from React. And then once this resolves, we are setting it to the puppies array that is set to state. And so while this is happening, we have a loading spinner inside the Suspense boundary and then when the data is ready, it swaps it over with this main component. And so Main is basically everything inside here. So if I refresh the page, you will see the loading spinner while the data is being

So if I refresh the page, you will see the loading spinner while the data is being fetched and then the data arrives and swaps over. So that's working, but there's a lot of complexity to it. We have to maintain code in two different places and then make sure that we have a loading spinner and we handle the error success states. Uh, and we can make this much simpler by bringing the data in-house inside our Laravel app that has this React and Inertia set up.

by bringing the data in-house inside our Laravel app that has this React and Inertia set up. And then we can literally not have any loading spinner because the data will be fetched on the server and then when we render the page, it already has the data. So you'll see that streamlines the process a whole lot. Let's get into it. All right, so speaking of data here in the previous application, the non Laravel application, we had studied the series by having an array of puppies,

Create Puppy Model2:32

the non Laravel application, we had studied the series by having an array of puppies, which he's typed to the puppy type. And so we wanna bring something similar to our Laravel app. So let's think about what we need. So we'll for sure want a Puppy model and database migration so we can bring along some puppies, we'll probably want a factory and seeder as well, although we might not need the factory, but we'll have a seeder just to have a set.

although we might not need the factory, but we'll have a Cedar just to have a set of default Puppys when we start the application. Uh, so let's start by creating the Puppy model and associated database migration. Alright, so in the terminal I'll go php artisan make:model Puppy. And so yes, we'll want a database seeder. I think we can get away without a factory but we definitely want a migration.

Design Migration Schema3:18

I think we can get away without a factory but we definitely want a migration. Alright, so it's created a model, a migration, and a site perfect. And we can start working in the migration file. So we need to think of what sort of table rows we want for the puppies database table. But if you remember in the previous lesson we've ported over the TypeScript puppy type and so that can probably inform exactly the sort of schema

the TypeScript puppy type and so that can probably inform exactly the sort of schema and shape that we want. So the ID is already there by default, uh, but we'll need a name, trait, image, URL, all strings. And then the likedBy is going to be a relationship, but we leave that likedBy field on ice just for a bit because it's going to be a specific belongsToMany relationship between users and puppies. So technically it's going to live in another database table.

to many relationship between Users and Puppys. So technically it's going to live in another database table. But also one thing we need to add is the user_id because every User in the application from the User model is going to own one of the Puppys. So when a Puppy is created, it should belong to a User. So let's make sure that we have the user_id reference in the database table for the Puppys. Alright, name trait image, URL, user_id. Let's do this. So the ID is here. Then we want table string for the name.

Alright, name trait image, URL, userId. Let's do this. So the ID is here. Then we want table string for the name. Yes, uh, not breed but I'll copy this And this is going to be trait and we need one more for the image URL and I'm never sure what to do here, but let's follow the snake_case convention that most php code seems to follow. So that's the field we need, but remember we also want a foreign ID for userId.

So that's the field we need, but remember we also want a foreign ID for user and we are going to reference the User class. Now if that User gets deleted, we also want to delete so we don't have orphan puppies, so let's have a constraint and cascade on delete. Just like that. Alright, I think that's a good starting point. So let's run the migration and then we are going to set up relationships.

So let's run the migration and then we are going to set up relationships between User and Puppy. Okay, php artisan migrate and it should run our migration. There we go. So now we should have a new puppies table in our database. Let's try to open database/database. Here it is in Table Plus and you can see we have this puppies database table with the structure that we have defined.

Add User Relationships5:31

and you can see we have this puppies database table with the structure that we have defined. Perfect. Alright, next, let's set up the relationship between User and Puppy. This is not the liked by relationship but more the ownership that a User can create Puppys and a Puppy belongs to a User. So I will go in the Puppy model that we've generated and here I will add a public function user, which is going to be type as belongsTo.

and here I will add a public function user, which is going to be typed as belongsTo. So that's gonna allow us to work out what User a Puppy belongs to. And on the other side of the fence for the User model, I will go and add, let's make it right at the start here. Public function puppies, a User can have more than one Puppy. So hasMany is going to be the relationship type. And again, this hasMany to the Puppy class.

So hasMany is going to be the relationship type. And again, this hasMany to the Puppy class. So that means that for a given User we are going to be able to work out what Puppy or Puppies belong to that User by using the puppies property or method. And so that's pretty handy. And then on the other side, on a given Puppy, we can work out which User that Puppy belongs to. Alright, good stuff.

Seed Users and Puppies6:37

we can work out which User that puppy belongs to. Alright, good stuff. Our next step I believe should be to bring some seed data so that we don't have to create all the puppies and users from scratch when we start a new version of the application. So we want to have like six to nine puppies and then one User and we can have all the puppies belong to that one User. So at least when we start, we have an app that looks sort

belong to that one User. So at least when we start, we have an app that looks sort of like the app looks now with a nice little list of cute puppies. So if I go in the apps/database seeds that comes out of the box by default you can see that there is one default User that will be created if we run the php artisan db:seed command. And so I'm going to customize this to Simon and the email is going to be Simon@laracasts.com. Uh, we can delete this 10 user placeholder.

and the email is going to be Simon@laracasts.com. Uh, we can delete this 10 user placeholder and let's run the php artisan db:seed. Alright, thank you very much. And so now if I go to the users table and we look at the data, you can see that Simon was created with the user_id of 1. Alright, so that's basic stuff. But now that we have that one User, we can create a Seeder for a bunch of puppies.

But now that we have that one User, we can create a PuppySeeder for a bunch of puppies and then we can make all these puppies belong to that one User. Okay? So when we generated our Puppy model and migration, we also generated a PuppySeeder that is placed here. So here I'm going to paste an array of puppies that I have prepared earlier. And as you can see they all have a name, a trait.

that have prepared earlier. And as you can see they all have a name, a trait and an image field. So the image field corresponds to the images that we moved over to the public directory. We'll change that later. But let's start with this for now. And the one thing that is missing from this data set is the user_id, but we can attach this on top of this data for each puppy. So let's do this. I'll go below the list of puppies

of this data for each puppy. So let's do this. I'll go below the list of puppies and I will go find my User that we've created. So I'll call it Simon = User::first(). So we'll grab the model and grab the first User and we'll just make sure that we always run that cer after the database seeder that creates the User so the User is present, okay? And then there's probably better ways, but here we'll just have a simple foreach loop.

And then there's probably better ways, but here we'll just have a simple foreach loop and for each puppy we will create a new puppy. So puppy, again, I'll import the model and then create. And let's accept the co-pilot suggestion. Uh, the userId name and trade seems legit, but the imageUrl, we not going to use this. Pick some photos.placeholder. So we want to use the puppyImage but we need to provide the correct path for it.

So we want to use the puppy image but we need to provide the correct path for it. So our images currently live in public. And then images, we will very likely want to change this to use I guess local driver and public disk. But for now let's try /images/ and then concatenate that with puppy image. So I think that should work. So now we need to actually call this siter. We can run it directly but I think because we want it to run

So now we need to actually call this Site. We can run it directly but I think because we want it to run after the user creation, it makes sense to go inside the DatabaseSeeder And after we generate a User, we call this uh, PuppySeeder right after. So in the DatabaseSeeder where we create a User immediately after this we can go, I think exactly like this, this call PuppySeeder class.

after this we can go, I think exactly like this, this call PuppyCedar class. Let's save. And so what I wanna do now is rerun the seeder. What I want to do is php artisan migrate --fresh and then use the --seed flag to run the seeder. So let's see what happens. Very cool. It's created our tables and then you can see that it has run the database puCedar. And so if we go back in TablePlus and a hard refresh, you can see the User

And so if we go back in TablePlus and a hard refresh, you can see the User assignment is still here. And if we go to puppies, we have our nine puppies all belonging to the user_id of one. This is definitely a starting point. Alright? So we can't replace the UI with these puppies from the database just yet because we don't have the liked_by and there's a few things to tweak around,

because we don't have the liked buy and there's a few things to tweak around, but let's try now to just try to bring these puppies into the welcome that TSX route and see if we can render maybe just a json string I list of these puppies and see if things works correctly. Then we're gonna have to deal with the images and we also want to create JSON resources so we don't pass too much data to the front end. Uh, let's start by just hello world printing,

Pass Puppies via Inertia11:08

so we don't pass too much data to the front end. Uh, let's start by just hello world printing, what data is available, see if we can bring that into the front end to the welcome page. Alright, so let's head over to our web.php routes file. And here where we render the welcome page, we wanted to pass some data and like I mentioned we're going to set up some JSON resources and do things a bit better. But for now let's have a puppies property.

to set up some JSO resources and do things a bit better. But for now let's have a puppies property and we are literally going to grab PU and return all of the puppies. And that's a very important point that puppyAll is going to replace the whole uh, data fetching with the API call, with the async function and then the loading spinner and all of that. We are going to be able to replace all of this by just grabbing the puppies from the database.

We are going to be able to replace all of this by just grabbing the puppies from the database and directly passing them to the Welcome TSX page component. So that's objectively much easier. Uh, I think it's makes life much simpler. Uh, like I said, we're going to tweak this and make it a little bit more robust than just puppy all but as a starting point, this is pretty cool. Let's check what happens in the front end.

but as a starting point, this is pretty cool. Let's check what happens in the front end. So I am passing a puppy's property to the welcome page and this is going to be available as a prop. So if I go to welcome, that's TSX and we go here in the main app component, this is going to receive the puppies and because we have a type set up, we can set it as an array of puppies. So we're gonna skip the whole error boundary suspense

as an array of puppies. So we're gonna skip the whole error boundary suspense that fetches the puppies from the other API. And instead here maybe just after the header I'll have a pre tag. And here we are going to JSON.stringify our puppies and let's go null, 2 to have some pretty formatting and moment of truth. Let's go see what we have in the front end.

and moment of truth. Let's go see what we have in the front end and boom, look at this. Here's our data. Uh, and you might have noticed that it was available immediately. So I'm going to hard refresh the page and you can see the data is here already. There is no fetching an external API and loading spinner. The data has been fetched on the

There is no fetching an external API and loading spinner. The data has been fetched on the server and passed to the view. So when the page renders, it already has that data so it can display it instantly. And so we don't need to have a loading spinner while something happens in the background and the data is being fetched. Alright? And like I said, we don't necessarily need all of this information.

Alright? And like I said, we don't necessarily need all of this information. We probably don't need the timestamps here and let's also try to test the relationship. So instead of the user_id, let's see if we can get the User data here for each Puppy. So remember on the Puppy model we have set this user property that is the belongsTo relationship. So in the web route I think that all I need to do is load the User that is attached to it and there you go.

So in the web route I think that all I need to do is load the User that is attached to it and there you go. Now you can see that we have the userId, but we also have the whole User model which represent this id. And this is a great example of why we want to set up JSON resources. We trying to display puppies here and we are not necessarily willing to display the user's email address.

and we are not necessarily willing to display the user's email address and you can imagine a few other sensitive fields in there. So in the next lesson we are going to set up resources for Puppy end users so that we only show what we want to show. We only pass what we want to pass to the front end because you need to think that React is a JavaScript framework and it'll receive props from the backend.

that React is a JavaScript framework and it'll receive props from the backend. So anything that you pass in the web.php route to the component will be available. So you gotta be careful of what you wanna make available. It's not like when you use a Blade template and only whatever you fetch in the view is going to be available here with Inertia, you pass everything over the wire into the client. And so even if you don't display it, it's still available.

Render Basic Puppy List14:56

you pass everything over the wire into the client. And so even if you don't display it, it's still available. So you gotta be a bit careful about this. But before we wrap up here, let's just try to display a random, not really good, but just placeholder UI for each puppy just to test that we can access the properties and the images and then we will make things much better in the next lesson. So in the welcome .tsx page instead of the json, that's string five here, we don't need it.

So in the welcome TSX page instead of the json, that's string five here, we don't need it. And because of the type I should have auto completes too. So let's have a card of bg-white padding-6 and let's give you the ring ring-black 10% opacity. Whoops, the /10 always break up the Emmet, but we'll go here. And inside of that we want an h2 tag. That is the puppy name, but whoops, we want to loop over the data.

That is the puppy name, but whoops, we want to loop over the data. So here puppies.map and for each puppy we are going to render this chunk. And so let's have the name, puppy_name, let's check where we're at. Okay, very nice. So it's working. Let me also uh, make an unordered list, which is flex gap-4 flex-wrap just for a tiny bit of like looks.

which is flex gap four flex wrap just for a tiny bit of like looks. And I'll turn this div into an ally item instead. Okay, nice. And let's give a margin top of four. Shouldn't care about stars but I can't help myself. Alright, that still looks terrible, but who cares? What I wanna try to do is make this card also a flex gap two container. And then inside here I want to have an image. So I'll accept that blindly and then see if it works.

And then inside here I want to have an image. So I'll accept that blindly and then see if it works. And yep, this the only thing I wanna change here that can be size and let's make it a bit smaller. And so you can see that this is actually correct because this is how we named the field in the database. But in our type here, our puppy type, the imageUrl is camel cased. So I won't change this because when we do the JSON resource,

So I won't change this because when we do the JSON resource, we will change it back to this. And so here we will ignore type script that is correct, but we know better famous last words. Uh, but let's check if we can see the image and we cannot. But this has nothing to do with the image itself. We just need to close the image tag properly, which copilot, uh, decided to not do. And so now I feel like I like my chances. And here we go.

uh, decided to not do. And so now I feel like I like my chances. And here we go. Check this out. The puppies are here. I'll actually make the image quite a bit bigger. Let's go double that 24. And we don't want the round it full here. And so there we go. This is not as cool looking as that. But we actually do have the puppies data coming directly from the database within our React and Inertia Laravel app.

directly from the database within our React and Inertia Laravel app. So if I was to change Yoko's name directly in the database to let's go uppercase YOLO and save that. Now when I refresh the page, Yoko has became yolo. Alright, this is pretty exciting. We have data, puppies data in the application and it's directly passed to the front end without any loading spinner, without any asynchronous fetch calls.

Plan JSON Resources Next18:02

to the front end without any loading spinner, without any asynchronous fetch calls. This is much simpler, much streamlined. Before we can use that data with the nice existing UI, I wanna do a few changes. Like I mentioned, I want to do JSON resources to only pass the fields that we want to pass. And we also need to set up the relationship for the liked status of each Puppy. So each User is able to like multiple Puppys.

for the liked status of each Puppy. So each User is able to like multiple Puppys. And so we are going to do this progressively. I think the next logical step is to do the JSON resources and we'll do that in the next lesson. See you there.

دوست دارید گاهی خبرهای Laracasts را ایمیل کنیم؟