Playing
02. One to One: Defining the relationship

Transcript

00:00
let's take a look at the easiest to implement but probably least used relationship and that is one-to-one. This relationship sets up a single model that can be used by multiple
00:15
other models. So although it sounds like a one-to-many type situation we're going to be accessing a single model on as many models that can share that particular thing. We can talk about this all day but let's just dive in and just start out with a very practical example. So I've got a completely fresh Laravel project here, we've got the database set up and migrated as we usually
00:37
would and we've got some users here. So we're going to go ahead and think of a common model that we're going to attach to any of our users. Now let's just use the example that is in the Laravel documentation just to keep things pretty really straightforward. So let's go over to our editor and we'll start to just first of all create a user. So let's go ahead and say php
00:57
artisan and tinker and let's go ahead and build up a user here. So let's say user factory and create. So that's going to go ahead and create a user for us so we've got one to work with. So the example in the Laravel documentation is a user and a blog post or something like that can both share images. Let's just roll with that example. So I'm going to go ahead and create out
01:23
a new model. So let's say make model and let's call this post. We'll create a migration and a factory alongside of this as well. So let's go over to the create posts table. We'll set this up in exactly the same way as we normally would so we don't really need to worry about anything specific in here in terms of the polymorphic relationship. So let's go ahead and just give this some really
01:45
basic data. We'll just give this a title and we'll just leave it at that. While we're here we'll head over to the post factory and let's go ahead and define out the title in here that we want to use. So let's use the fake helper. We'll say sentence with six words and that'll allow us to generate that out. Okay let's go over and run php artisan migrate. So notice at this point we've done nothing
02:09
specifically to link another model to any of these two. That's where the polymorphic relationship comes in. Okay so let's go ahead and make out a model that we can attach to both of these things. So this is going to be something like image. Again this is in the Laravel documentation so it makes sense that we can cross-reference it if we need to. So we're going to create this image out and
02:31
this image is going to be a predefined thing in our database. This could be like a country, it could be pretty much anything but we want to be able to link this up to both the user and the post that we've just created. So let's again create out a migration and we could do a factory although we're probably going to manually do this in the database and let's go ahead and open up the create images
02:54
table. So this is where wherever you are wanting this image to be attached to something we define in here. So let's just go with the example in the Laravel docs and we'll create a string out for a url for the image and we are going to add in here two columns. Now what we're not going to do here is say something like string and imageable type we'll discuss these in just a second and integer
03:23
imageable id. Now these two things as we sort of saw from the introduction this id is going to be what model id we want to hook this up to. So in our case we've generated one user which will be the user id of one. The imageable type will be the model that we're working with and we'll make a slight adjustment to this later on in the course. So this is going to be something like app and models
03:48
and user. So that is how we define out a polymorphic relationship in pretty much all of the polymorphic relationship types. Now the problem that we've got here is this is a little bit brittle it doesn't follow the convention of the Laravel framework in terms of how the schema is created so we have a table morph and let's just say morph and then we just give the name of whatever thing
04:15
it is. Now the name of this is up to you but we're going to use the naming convention so we don't need to change and configure too much in our models. So what we do when we are naming these polymorphic relationship things that can be a part of this particular model is we give the name of the model which is image and we make it able so imageable whatever we want to say. So if we just do morph
04:39
imageable that's all we need to do that will generate the columns that we need. So I think that's just good for now let's go ahead and run a migration on this so let's say phpr to migrate and let's hop over to the database and just see what we've got in here. So we've got our posts table which we've already spoken about we've got our users table we want both of these to be able
04:59
to contain one of these predefined images and you can see here we've got imageable type and imageable id created. Now let's just type into the structure of these just so we understand exactly what's being generated here so this is a string a bar chart 255 notice it's not nullable so it does need to be filled in because otherwise we're not going to know what's what and let's just have a
05:20
look here there's nothing really else in here that we need to worry about and we have an unsigned big integer for the imageable id which is more than capable of handling any of the ids in any of the tables we want to associate this to. Okay so now that we've got the schema down this should give you a good idea as to how these get linked up but of course what we need to do now is we need
05:42
to go ahead and define these within the actual models itself. So a good first step is to go over to the actual image model itself now how do we make this thing polymorphic now again this this is going to be a very similar pattern to a lot of the other polymorphic relationships we talk about but we're going to create out an imageable again that's the key part of this that's the name of the
06:06
column that we gave and this imageable method or in this case a relationship is just going to return this morph to so we can access this and I'll show you how to access this a little bit later like a normal Laravel relationship now that we've done this what we can do is we can choose now so any of the models that we want to be imageable we want to contain a particular image we can just do
06:33
that really easily so over in the user model here we can go ahead and we can define a relationship down here and say well what image is this what image are we giving to this particular model we're going to say return this again like a standard relationship but we're going to use morph one so with this we're going to provide in the model name which is at models image the fully
06:56
qualified class name to that and then as the second argument we're going to provide the abl thing that we gave the name for which is in this case imageable now with this we can pretty much just take this and copy and paste it to any of the other models that we want to be imageable which we know in our case is this post so let's go into the post model let's pull this down and by the
07:18
way what you can do if you want to type in these you can type these as a morph one return type as well so let's go ahead and do that for this just here say morph one and you can do that for morph two as well over in the actual image so let's go over to here and we'll say morph two and set that return type so entirely up to you if you do want to do that it's optional okay so now
07:45
what i want to do over in say web roots we're going to grab the user that we created so we're going to find that by one let's just make sure we pull the namespace in for user just here and while we're here let's do the same thing for the post as well because we know both a post and a user can contain an image so let's just generate our post as well here so let's say phpr st tinker
08:10
and we'll say post factory and create that should work and no let's go and say app models post okay great so we've created that out let's go back over die dump both of these just to make sure this is working and yeah there we go great so we've got the two instances of these models let's die down on user and remember now that we've created that image relationship in that polymorphic
08:39
relationship of course we get null now the reason we get null is because this is a one-to-one relationship we don't get back an empty collection think of these pretty much identical to a one-to-one relationship and a one-to-many relationship within normal eloquent relationships it's just the way that we define them with the ability to set these to any model type is the only difference so user
09:02
image brings back null because we don't have anything assigned and post image also brings back null okay let's swap this over to user image let's go over to the database and let's create out an image in here to hook this up now at this point if you're wondering why do we need to set this up in this way could we not just set this up as a normal relationship type with a one-to-many well
09:28
if we think about it what we want to do is we want shared models between two different model types now if for example we had created this let me just get rid of this if we had created out this images table normally what columns would we have we probably have a user id to link it back to the user which this image belongs to but then that means we can't link that to post as well so the
09:56
point here is that we have the flexibility through the polymorphism of these two things that we can link out to both things that's pretty much why polymorphic relationships exist in the first place so for url i don't really care what this is i'm just going to set this to abc we're going to manually fill this in first and then i'm going to show you how to go ahead and
10:15
actually insert these so what's the imageable type well it's app models and this is a little bit awkward and we're going to get a better way to do this later and that's user so i want to hook this up to user one i'm going to fill in created out and updated out i'm going to save this out and that is now hooking up this image url which obviously is just a fake one to user one so let's
10:39
go back over to the browser let's give that a refresh and there we go so now this user has a image specifically for them now the beauty of polymorphic relationships is what we can now do is we can say well i want a post to have a image so i'm going to say post one also has this image as well that saves us from creating an in a user images table and a post images table we can keep
11:09
them all in one place and they can be hooked up to any model from here even ones that we create in the future so let's go back over to our editor and let's just change this over to post image just to verify that this works and there we go we get exactly the same thing for there so when the time comes when you're building something and you think i really need to hook a sort of similar
11:33
thing up to two different models and i just need one of them then obviously this polymorphic relationship is gonna work really nicely so now that we know how to set up this polymorphic relationship let's head over to the next episode and let's talk about how we insert these because at the moment we've just done this directly from the database

Episode summary

In this episode, we dive into Laravel's one-to-one polymorphic relationships. While these are super flexible, they tend to be underused, possibly because their purpose isn’t always obvious at first.

We start off with a fresh Laravel project and talk about a common real-world scenario: sharing an image between different models, like Users and Posts. Instead of duplicating columns or creating a bunch of different tables (like user_images and post_images), a polymorphic relationship lets us tie an image to any model we want, now or in the future, using just one images table.

We go step by step, creating the necessary models, migrations, and factories using Artisan. Then, we work through the database changes, showing you how the polymorphic columns (imageable_id, imageable_type) work. We also discuss Laravel's naming conventions, like using morphs('imageable') to keep everything clean and conventional.

Once we’ve set up the tables, we jump into the model code, defining the actual relationship methods using morphTo, morphOne, and highlighting how these make the images accessible from both users and posts. We test this out in Tinker and explain why accessing the image returns null until one is actually assigned.

Towards the end, we manually insert an image into the database linked to a user, see it showing up on the relationship, and then show how the same structure allows us to swap it over to a post easily. The big takeaway: if you need to connect a single resource to different kinds of models without creating lots of extra tables, one-to-one polymorphic relationships are the way to go. Next up, we’ll look at how to insert these records more easily from code.

Episode discussion

No comments, yet. Be the first!