Defining One-to-One0:03
The one-to-one relationship is the most simple relationship. It basically says that one record in one table is related to one record in another table and there aren't any other records part of that relationship. It's a one to one relationship. It's also very much like a parent child relationship because one record is, well, it's, it's the main record, it's the parent record.
because one record is, well, it's, it's the main record, it's the parent record. Whereas the other record that's related to it is a child record. You can kind of think of it as, you know, a user and a user is going to have a profile. So the profile would be the child, the user would be the parent. And you know, whenever we create a Laravel project, we are given a user's table by default
Creating Profile Migration0:43
And you know, whenever we create a Laravel project, we are given a user's table by default and not just the user's table, we also have the model. But when it comes to setting up relationships, there are essentially two layers involved. The first layer is the database layer and we need to define the relationship there, but we also need to set up the relationship in eloquent. So let's go ahead and start by creating a profile table. We'll use Artisan to make a model and we'll call it profile.
So let's go ahead and start by creating a profile table. We'll use Artisan to make a model and we'll call it profile. Let's use dash M to create the migration and let's start with the migration because that is where the relationship is going to start. So of course every migration begins with a primary key, which our profiles need a primary key and then the timestamps. But there's also some information that, you know, a profile is going to need something like a bio.
But there's also some information that, you know, a profile is going to need something like a bio. So let's include that. But I would say it's not necessary. So we can say that it is nullable and let's also say that our users can have a handle, but once again, it's not necessary. So we'll make that knowable. Now of course these columns don't do anything as far as a relationship is concerned. What we do need is a column that basically says
Adding Foreign Key1:56
as a relationship is concerned. What we do need is a column that basically says that this profile belongs to a particular user. So we are going to create what's called a foreign key. To do that, we use the foreign ID method and then we give the name of the column, which the convention is to use, the type of record that we are working with, in which case it's going to be a user, and then the name of the key column in that table, which is an id.
to be a user, and then the name of the key column in that table, which is an id. So if we look at this column name, it is a user id and it is set up as a foreign key. So a foreign key is basically just a column that we set in a a table that says we intend to store the key for another table. So if you think of a table as you know, its own little country records inside of another table would be foreign to that table.
its own little country records inside of another table would be foreign to that table. So what we end up with is a foreign key that references the user ID that will essentially own this profile. And just by doing that, we've set up the relationship and we can go from here and that's fine. But there are some things that we need to be concerned with because especially with a one-to-one relationship, you know, ideally every user would have a profile,
because especially with a one-to-one relationship, you know, ideally every user would have a profile, but not every user is going to have a profile, which is something that we'll get into here in a moment. But we want to ensure the referential integrity between these two tables. Basically, that just means that if we have a profile, we want to ensure that we have a user for that profile. And we also only want one profile for one user. We don't want a user to have multiple profiles.
And we also only want one profile for one user. We don't want a user to have multiple profiles. That kind of defeats the purpose of a one-to-one relationship. So there's a few things that we need to do to enforce that one-to-one relationship at the database level. And we're gonna start by using the constrained method. This is what is going to start setting up the referential integrity between these two tables so that
to start setting up the referential integrity between these two tables so that whenever we create a profile, that profile has to be created for a user that exists. But what happens if we delete a user? Well, by default the user is deleted, but the profile isn't, it is still inside of the database, which means that we end up with a record that has no parent. It's what we call an orphaned record. So whenever we delete a user, we want
It's what we call an orphaned record. So whenever we delete a user, we want to also delete the related profile and we can do that with this cascade on delete method so that if we delete a user, the database is automatically going to also delete the profile. But still, this isn't going to force a one-to-one relationship because as it is right now, we can create a user
a one-to-one relationship because as it is right now, we can create a user and then we can create multiple profiles for that user. Now, when it comes to the eloquent side of this relationship, we can kind of enforce that, but you know, a lot of times we just want to enforce that at the database as well. Just it helps prevent problems. And in which case, what we could do is say that the value in the user ID column has to be unique,
And in which case, what we could do is say that the value in the user ID column has to be unique, and that is what's going to enforce this one to one relationship. So that whenever we create a profile for a user, we can have only one profile for that user because the value in the user ID field is unique. With all of that in place, we can migrate our database and really we want to seed it as well because that is going to give us at least a user
and really we want to seed it as well because that is going to give us at least a user that we can play with. So let's run DB CED as well, or at least it should. Let's take a look at the database. Cer, uh, database CR does create a user. Great. So we have a user, and I'm just noticing we didn't save that file. So what did our body creation run? Uh, so let's do this just to make sure we'll run,
So what did our body creation run? Uh, so let's do this just to make sure we'll run, migrate fresh seed. That way everything is wiped and the migrations are run and the database is seeded once again. So from a database perspective, we are set to go as far as our relationship is concerned, but we need to set up our eloquent models to include that relationship because our eloquent models are how we are going to work
Defining Eloquent Relations6:30
that relationship because our eloquent models are how we are going to work with the data and by themselves. The models don't know anything about the relationship. We have to define those. So we'll start in the user model. And what we are going to do is create a public method called profile. The idea being being that this is going to essentially define the relationship to the profile. And this is a has one relationship.
to essentially define the relationship to the profile. And this is a has one relationship. So whenever we call this profile method is going to return a relationship object. In this case it's going to be a has one relationship and all we need to do is return has one, and then we specify the related table. In this case it's going to be profile class, and that's all that we have to do. Now, the reason why this is all that we have to do is
and that's all that we have to do. Now, the reason why this is all that we have to do is because we have followed convention, if we go back to our profiles migration, whenever we created our foreign key, we used the basic convention to define a foreign key. In that case, it is the name of the record that we are trying to match to. And then the key of that table. So it's a user record, the key for that table is id, so
And then the key of that table. So it's a user record, the key for that table is id, so therefore it's user underscore id. But because we have used convention here inside of our model, eloquent is automatically going to know the name of the foreign key. So anytime that we want to use this profile method to work with that relationship, eloquent behind the scenes automatically knows that hey, the profile or the relationship for this user is based upon
behind the scenes automatically knows that hey, the profile or the relationship for this user is based upon a foreign key of user id. Now we don't have to follow that convention. If we wanted to call this column, who cares? We could do that. The only thing that we would need to do whenever we define the relationship inside of our model is say that hey, we have a different foreign key and it's called who cares. And there are times that you won't follow convention,
we have a different foreign key and it's called who cares. And there are times that you won't follow convention, but most of the time you will. So just know that that is there. You don't have to follow convention. You can name your foreign key column, whatever you want, but whenever you do, you need to tell eloquent that you didn't use the default foreign key. Okay, so we have set up the relationship on the user side. This is going to allow us to access the profile from a user,
Okay, so we have set up the relationship on the user side. This is going to allow us to access the profile from a user, but we also want the reverse. We want to work with a user from a profile. So inside of our profile model, uh, let's first of all set up the protected fillable and what do we have bio and handle. So we'll be able to fill those in. And then we will have essentially the same kind of thing, except that in the case of the profile, we want to find
And then we will have essentially the same kind of thing, except that in the case of the profile, we want to find or work with the user. But this is a slightly different relationship. It's not a has one, it's a belongs two. Because remember I said that this is more like a parent child. So the parent is the user, the child is the profile. So the user has one profile, the profile belongs to the user, but still it's going to be the same thing to
So the user has one profile, the profile belongs to the user, but still it's going to be the same thing to where we will return a relationship it's called belongs to. And then we specify what this profile belongs to. It belongs to a user model. And once again, since we follow conventions, our primary key is ID because that is what the ID method gives us. We don't need to specify anything else here. We just say that hey, the profile belongs to the user
Displaying Related Data10:22
We don't need to specify anything else here. We just say that hey, the profile belongs to the user and behind the scenes eloquent is going to magically match all of that together. So great, let's use that relationship. Let's open up our routes. And you know, this is just a plain Jane Laravel application has no customization except for what we just did. So what I want to do is this inside of our main route here, we are going to fetch the user
So what I want to do is this inside of our main route here, we are going to fetch the user and then we're gonna pass that user to the view. Now of course, the view doesn't do anything with this user object, so we will need to change that, but that's gonna be easy enough. We just need to open up welcome blade PHP. And you know what? Let's do this. Let's take out everything inside of Maine. So this diviv element here, let's take that out
Let's take out everything inside of Maine. So this diviv element here, let's take that out and really let's take out everything inside of Maine. That way we have just an area that we can display information. Now the background is gonna be black, so let's set the text to white and then we will just output everything that we need. So we'll start with the username. So we will have username, then we want the user
So we'll start with the username. So we will have username, then we want the user and the name property, and let's also do that with the profile information. And really we just want the bio. Let's start with handle first. Handle makes a little more sense than bio and then handle. So then we just need to access that information. And all we need to do is a profile, just like it were any other kind of attribute.
And all we need to do is a profile, just like it were any other kind of attribute. And then we would use our attribute handle in this case for the bio profile and then bio. Now what you might be thinking is, these are properties we defined profile as a method inside of our user model. And yes, absolutely we did. And this is where eloquent starts to really do some magic behind the scenes because while we have defined profile
And this is where eloquent starts to really do some magic behind the scenes because while we have defined profile as a method in order to access the actual information from the database, meaning that hey, we want you eloquent to go ahead fetch the profile for this given user, and we want to display that inside of our view, we use it as a property. Now, I know that that can get a little confusing and we will talk about that here in a few moments,
Now, I know that that can get a little confusing and we will talk about that here in a few moments, but for right now that that's all that we need to do. So if we take a look at this in the browser, we're gonna see in error because it is attempting to read a property handle on null. Why? Well, it's because we didn't create a profile yet. We have a user, but that user doesn't have a profile. So there's a couple of things that we can do in this case to
We have a user, but that user doesn't have a profile. So there's a couple of things that we can do in this case to um, prevent an error like this because you know, not every user's gonna have a profile until they create one. So one thing that we can do is just handle this directly inside of the view. You know, we could use optional chaining here so that if we do have a profile, then everything's gonna be fine.
that if we do have a profile, then everything's gonna be fine. If not, then we can give it a default value. That's certainly one way, but that kind of muddles up our view. Instead, what we can do inside of our relationship, if we don't have an actual profile, we can say with default, basically we just define the attributes for this relationship, in which case what we had the handle. And we could say that no profile is set for this user.
for this relationship, in which case what we had the handle. And we could say that no profile is set for this user. And then we could essentially do the same thing for the bio. So basically, if we tried to access the profile, that doesn't exist for a user, these default values are going to be used for those attributes, in which case we can go back and we can see, you know, everything works. Our view is clean as it was before, and now we are providing default values for the handle
Our view is clean as it was before, and now we are providing default values for the handle and the bio if a profile doesn't yet exist. But of course we want a profile to exist. So let's do this. Let's go back to our routes. I think we're done with our views. So let's close that and let's create a get route for Create. And all we are going to do is create a profile, but first of all, we need to get our user.
And all we are going to do is create a profile, but first of all, we need to get our user. So we will find that one user and then we can create a profile in a couple of different ways. The more straightforward thing to do is to call profile and then call Create. Then we can specify the bio. Since this is our first user, we could say that his bio is, um, the first user
Since this is our first user, we could say that his bio is, um, the first user and then for the handle, um, you know, we could do something like first or something like that. He, he's really proud that he's the first user and that's it. That's going to create a profile and attach it to that user. Now notice here we are using Profile as a method. So okay, it can be confusing, yes, but just think of it in these terms.
So okay, it can be confusing, yes, but just think of it in these terms. Whenever you want to work with the actual data in the database, you use the relationship as a property, just like we did inside of the View. So user profile as a property, and then we access the individual values that we need. Now we use the relationship as a method, anytime that we want to do something with that relationship, such
Now we use the relationship as a method, anytime that we want to do something with that relationship, such as, you know, creating a profile or, uh, we could also customize the query, which in this particular case doesn't really gain us anything because we're fetching one record based upon the user id. And that's it. There's really no other reason to customize the query here, but that is the primary difference
to customize the query here, but that is the primary difference between using the relationship as a property and using it as a method. So this is the more straightforward thing to do, but we can also do something like this. We can create a profile by just newing up the profile constructor, and then we can supply, you know, the individual values, which I'm just gonna copy and paste there.
and then we can supply, you know, the individual values, which I'm just gonna copy and paste there. But this by itself doesn't do anything inside of the database. This just creates a profile object inside of our application. We have to tell eloquent, Hey, we have this profile, we want to save it for a given user, in which case we would once again call profile because we are doing something with this relationship.
in which case we would once again call profile because we are doing something with this relationship. And we'll call save, we'll pass in the profile object that we created, and that will save that profile for that user. So there we go. Two ways to create a profile and attach it to a user, which either way makes sense to you, is really the way that you should go. I'm gonna go with Just Calling Create. So by doing this, we will be able to create a user
I'm gonna go with Just Calling Create. So by doing this, we will be able to create a user or create a profile for that user. And then whenever we view it inside of the browser here, we will see that actual information. So, uh, well, let's just do it all in this one tab. So we will call Create. We don't have any feedback as to whether that created or not, but we can go back, we can refresh, and sure enough, the profile information is now there
or not, but we can go back, we can refresh, and sure enough, the profile information is now there and available for us to see. Now, behind the scenes, eloquent is going to make our lives as easy as possible. Like for example, the only query that we explicitly performed was fetching our user, and that was it. Eloquent is gonna go and fetch that record so that we can use it. But inside of the view, we did more than just use the user.
and fetch that record so that we can use it. But inside of the view, we did more than just use the user. We also used the profile. And the minute or the moment that we tried to access the profile, eloquent decided, Hey, you're gonna want this information. I'm gonna go and fetch it for you. So it's an on demand feature, which is fantastic because while we want that behavior, it saves us from having to explicitly say, Hey, go ahead
because while we want that behavior, it saves us from having to explicitly say, Hey, go ahead and get the profile for this user as well. But there are times when we want to eagerly load data. Like for example, let's say that we have a hundred users. And you know what? Let's just do that because there's nothing like actually seeing that happen. So inside of our database, C, let's comment out where we create that single user
So inside of our database, C, let's comment out where we create that single user and we are going to create 10 users, but for each user we want to create a profile. So we're going to get the user so that then we can create our profile where the user ID is going to be the provided user id. We also want to set up the bio, which in this case we'll say it's the default bio four, and we will include the user ID there.
which in this case we'll say it's the default bio four, and we will include the user ID there. And then finally we have the handle, which once again, let's do something unique for each user. So we'll have the user followed by the user id. So we're gonna have a hundred users. Those a hundred users will each have a profile, we need a use statement there. So let's go to the command line and let's migrate fresh so that now inside
So let's go to the command line and let's migrate fresh so that now inside of our default route, we don't want to get just the first user, we want to get all of the users. So we will simply pass that onto the view so that inside of the welcome view, we will do this for each user as user. And then we want to display the user information. And I don't necessarily know if we want to keep, well,
And then we want to display the user information. And I don't necessarily know if we want to keep, well, let's just keep the same thing because we already have that there. It makes it a lot easier. So now whenever we view this in the browser, we see a lot of information. We see the username, the handle, and the bio for each users. It's all jumbled together.
We see the username, the handle, and the bio for each users. It's all jumbled together. But you know, that's gonna be fun. We have 10 of those users. But let's take a look at the database. Let's see what happens here. So I have telescope, and this is going to let us view our queries. So let's go back and refresh. And lo and behold, we have several queries.
So let's go back and refresh. And lo and behold, we have several queries. Now we'll start from the bottom. We'll see that we are selecting all of our users. That of course is obvious because we did that. We fetched all of our users so that we could supply that to our view. But then let's take a look. As we iterate over all of those users, we are making individual queries
As we iterate over all of those users, we are making individual queries to retrieve the individual profiles for each user. And this is a performance problem. We call this an n plus one problem in that we can have a variable amount of queries that is the N in n plus one. In this case, N is 10. We have 10 extra queries for getting the profiles of each individual user, and then plus one.
We have 10 extra queries for getting the profiles of each individual user, and then plus one. That is the first query that we made selecting all of those users. So imagine having to display a hundred users or a thousand users. This is a performance issue because for every user, we are hitting the database to retrieve the profile for each user. Now granted, the reason why we are getting this behavior is
Eager Loading Relationships22:13
to retrieve the profile for each user. Now granted, the reason why we are getting this behavior is because eloquent by default fetches that information on demand, which is great except for this particular circumstance. So what we want to do is essentially eager load all of the relationship information whenever we fetch our users. And we can do this in a couple of different ways, but what we will talk about in this episode is the width method.
but what we will talk about in this episode is the width method. Basically, we want to fetch our users with the relationships that we want to load. In this case, it's just profile, but if we have multiple relationships, we could pass in an array of those relationships. And then we just want to get those records. And so that's now, as far as the browser is concerned, we get the same results.
And so that's now, as far as the browser is concerned, we get the same results. But if we take a look at telescope, we see something drastically different. We still have our query to select all of our users, but now we have another query that selects all of the profiles for those users. So we are eagerly loading all of the profile information before we even use it. Now granted, if you're just working with one user
before we even use it. Now granted, if you're just working with one user and one profile eagerly loading, that information isn't really going to gain you much. In fact, it's really not going to gain you anything at all. But if you are working with multiple records, and not just those records, but the relationships for those records, then you will want to eagerly load that data. Now, there are other ways that we can eagerly load data,
to eagerly load that data. Now, there are other ways that we can eagerly load data, which we will talk about later. But there's one other thing that I want to talk about and that is the inverse relationship. So, so far we've been talking about, you know, getting a user and then accessing the profile from that user. What if we have the reverse? What if we have the profile
What if we have the reverse? What if we have the profile and we want to get the user that way? Well, it is the same concept that we've been talking about because we set up that inverse relationship inside of our model. You know, our user has the profile relationship, but our profile model also has the user relationship and it's gonna work the exact same way, except it's in opposite.
and it's gonna work the exact same way, except it's in opposite. So if we wanted to fetch a given profile, which let's just find the first one and we wanted to work with the user, we just access it as we normally would, any other attribute. And then from there we can get to the name or the ID or whatever information that we need from the user. So one-to-one relationships are the most simple relationships, not just in Laravel and eloquent,
So one-to-one relationships are the most simple relationships, not just in Laravel and eloquent, but in programming in general. One record relates to some other record in the table, and that's it. There's no other relationship there. Now, in the next episode, we're gonna take this a step further and talk about the one to many relationship.
and talk about the one to many relationship.
