Introduction and Lesson Overview
Welcome back. In this lesson we're going to be looking to associate our customers with a company, and the first part of this is going to be a bit of a review. We're going to create a model and a controller, and then we're going to get to the actual meat of this lesson, which is Eloquent relationships. So stick around and you'll see how easy it is to have relationships with Laravel and Eloquent. The first thing we're going to do is we're going to go to our console and we need to generate a model. So we'll say php artisan make:model. And what's the model going to be called? Remember our models are a singular version of what we are going to do, so we're going to have companies but our model is going to be Company. So Company, and if we need the migration to go with it we're going to add the -m flag. So there we go. So we've created a model and we've created a migration.
Creating the Companies Migration and Model Setup
Back in PhpStorm let's start with our migration. So it's going to be called creates companies table, and so let's keep it simple. I'm going to add a string for name and that would be company name, and maybe let's just add one more for phone just to keep it very simple. We're going to do just a name and a phone. Let's go ahead and hit save. So let's take a look at our Company model and it's going to be called Company and that's inside our app directory just so we keep track of this inside our app directory here. This Company, as I've mentioned before, I almost exclusively always have my mass assignment protection turned off, so I'm going to do that now. protected $guarded = []; And if you're unsure about mass assignment check out the previous lesson where we go into in-depth between setting fillable fields or setting the guarded property to an empty array. So now that we have guarded off it is basically turned off completely. Up next I want to create a company, so obviously right now I don't have a view for that yet, so the easiest way is to boot up php artisan tinker and let's whip up a new Company.
Creating Companies with Tinker and Initial Review
C = new Company; and of course we can use this notation because we added our $guarded = [] otherwise remember this will give you a mass assignment error. So now we can say name: "ABC Company" and we'll have a phone. All right, those are the two fields that we had added, so phone: 1231231234. All right, so now we have a company in our database. So far this is all review, right? We've done all of this before, so hopefully it's starting to feel a little bit better in terms of flow. Now here's the new part of this: this company is going to have some customers, right? It's what we call customers. So a customer to us has an associated company. So the way to think of that is we can say a Company has many Customers and a Customer belongs to a Company, and that's exactly how we're going to write it. So let's head back to PhpStorm.
Defining hasMany and belongsTo Relationships
This is my Company model and let me pop open my Customer model. I'll pop them open side-by-side. So let's add a new relationship. This is how you do it: in my Company model, remember a Company has many Customers, so we'll add a new public function called customers, and inside this method return $this->hasMany(Customer::class). This public function is called customers and customers again is the plural of Customer. If you keep to this naming convention of singular to plural everything just works. You can always override this if you don't want to follow the convention, but for now just to keep it simple, just follow the convention. So public function customers: a Company has many Customers. Then let's write the inverse in our Customer model: public function company singular, and we'll say return $this->belongsTo(Company::class). And that's it. Just like that our Customer is associated to a Company and our Company is associated to a Customer.
Adding the company_id Foreign Key and Migrating
We have one last little thing that we need to take care of and that is the foreign key in our database. In order for us to associate a Customer to a Company that Customer has to store a company_id. So let's take a couple of steps back and take a look at our create_customers_table so far. In this table we have the name, the email, and this active column that we worked on a couple of episodes ago. So we need to add a new entry here: unsignedInteger('company_id'). So that's the convention: we have a Company model and then on our Customer we have to add a company_id. So this hit save. I know that I had already created a Company in Tinker; we're going to have to create that again. So let's do php artisan migrate and I'm just going to call the fresh, and fresh will give us a blank database altogether. But we do see here we have our customers table and we have our new companies table. So let's create a Company now. I'm going to use php artisan tinker again. company::create and remember I can use the create method because I already set my $guarded equal to empty array. So we'll quickly say name: 'ABC Company' and the other field we had was just phone and we'll say 1231231234. All right, so create that Company for me. Perfect. In our form, in our customer form, we need to add a dropdown so we can actually select the appropriate Company for the Customer that we are creating. Eventually of course we'll have to add a form to be able to add Companies, but for now we'll keep it simple and do this. This is not for active; this is going to be for company_id and we'll say 'Company'. So for our select here of course we're going to have to pass this data to our view. So let's go to the Customer controller and let's see what we need to do here. Our list is currently getting a list of active customers and a list of inactive customers, so we're going to need a list of companies and we'll do that simply by calling the all method on it. We can always scope this down to active companies and stuff like that; again we're keeping everything as simple as possible. Let's go ahead and pass that into our compact. So let's use the Blade syntax: @foreach($companies as $company) and @endforeach. What we're going to have here of course is an option for each where the value is going to be company id and the name is going to be company name. All right, let's check it out in the browser. Refresh, and there we are. So obviously ABC Company is the only company we have in our database right now.
Let's add a customer. We'll say John Doe, [email protected], status active, ABC Company, add customer. We get an integrity constraint violation. The reason why this happened is because remember we are validating specific fields; we did not update that in our controller. So let's take a look at that now. Right here we have name, email, active; let's add a new one for company_id and we do know that that is required. All right, let's hit refresh and there we are. So we added this customer. Check this out: I'm going to boot up php artisan tinker one more time because I do want to show you this relationship. I'm going to fetch my Company and we're going to fetch that by saying Company::first. So now we have Company saved to this company alias. If I say company->customers, there we are. So we've associated John Doe to this Company right here. And we can do the inverse of that, so we can say Customer::first and let's say customer->company. So we are able to associate a Company to a Customer. I want to use that relationship right now to reflect that in our Customer view. So we were using the email but what I actually want to do is instead of the email I'm going to fetch the company relationship. So we'll say activeCustomers->company->name. Again activeCustomers is fetching the company relationship which we established in our Customer model. Notice that we are calling it without using parentheses; we are not calling company() parentheses; it's company as a property. We'll take a look at the difference between calling it as a property or calling it as a method but for now just remember: no parentheses. So activeCustomers->company->name, is it safe? Let's check out what we get. We are able to get that ABC Company right into here. That's pretty cool. In my view I actually want to add one more little section and it's just to prove that we can fetch the relationship in the other direction. So let me add a row and for now we'll just keep it as a column of 12 inside, and here let's just do @foreach($companies as $company) and for each let's output the company's name in an h3 tag: {{ $company->name }}. And then I want to fetch all of the company's users. We'll keep it simple and keep going with this. There's a better way of doing this but for now we'll just say @foreach($company->customers as $customer) and that's going to give us a collection; as $customer we'll wrap this in an unordered list really quick here with
{{ $customer->name }}. End foreach and end ul. All right, let's check out what we have now. So right now ABC Company has one customer John Doe and the way we fetched that relationship was by calling company and then fetching all of their customers and then we're iterating through each of those customers as customer and outputting that to an unordered list. And then we have at the top we are using it to fetch the company's name. So right up here we have our active customer; we're fetching their company and fetching the name of the company. Again the relationship for that came from our model. In this case this is the Customer model; we have this company relationship here established. And in our Company model we have a customers relationship here established. In our migration for our Customer we did add a company_id which is obviously a foreign id for the customers table and this is what represents our Company. And then from there now everything just works. I'm going to add one more Company and add a new Customer to it so you can see it all working in the browser. So let's add the first Company first; I don't have a view for that so I'm going to have to revert back to adding it through here. Let me go up a couple of clicks here. So we'll have a new Company and this Company is going to be called the DEF Company. Now let's go back to the browser. I'm going to hit refresh and so now we have the ABC Company and we have the DEF Company. Let's add Jane Doe to the list and Jane is
[email protected]. We'll make her inactive; it won't make a big difference. We'll hit add customer and there we are. So we have Jane Doe associated with DEF Company, John Doe is associated with ABC Company, and we are able to fetch all of the customers for each of these companies. To prove that I'm going to add a third person here and we'll call them John Smith, john@example is fine, add customer. So that John Smith and John Doe both belong to ABC Company as we see it here, and Jane Doe belongs to DEF Company as you see it here. So the hasMany and belongsTo relationships are probably one of the two most used of the Eloquent relationships, but we're going to continue to work on relationships throughout this series and we're going to dive deeper through all of them just like we did with these two. So keep playing around with these relationships and adding more tables and trying to associate them, and when you're ready we'll move on to the next lesson.