This tutorial will show how to do a parent/child relationship on the same model, in the same database. What we will be doing is expanding our data for adding cafes by allowing the user to add multiple locations for each cafe. These should be stored as an individual record in the cafes table. This will be a perfect example of a parent to child relationship in Laravel.

Step 1: Define our Data Structure

Let’s use Milwaukee’s Collective Coffee Colectivo Coffee Roasters and Cafes and Los Angeles’ Bar Nine Bar Nine coffee shops as examples. Colectivo has multiple locations around the city, but the same coffee shop. Bar Nine has one location in Culver City, Los Angeles. Bar Nine will have 1 record and location in the database. Colectivo will have many records in the database, with a parent ID and one parent ID record.

Parent/Child relationships can get very complicated very quickly depending upon how far down the tree you travel. In this case we have a simple parent to child relationship and that’s it.

Why would we want groupings like this? Look at the home page of roastandbrew.coffee. There is a card for each cafe. Instead of 15 or so cards for Colectivo, we can have 1 card that says they have X amount of locations. We can also define the brew methods at each location. Airport or small cafes might not have all of the brew methods other cafes have. With an individual record in the cafes table, we will be able to do many to many relationship we set up in the last tutorial https://serversideup.net/many-many-relationships-laravel/ on that child record with the brew methods available.

This might be confusing now, but hopefully after this tutorial it will make more sense. If not, feel free to reach out!

Step 2: Add Database Columns in Migration

We need to add some database columns to our cafes table so we can set up this relationship.

Open your terminal, connect to your web server and run:

php artisan make:migration added_cafe_parent_child_relationship

Open up the migration file and add the following to the up() method:

Schema::table('cafes', function( Blueprint $table ){
  $table->integer('parent')->unsigned()->nullable()->after('id');
  $table->foreign('parent')->references('id')->on('cafes');
  $table->string('location_name')->after('name');
  $table->integer('roaster')->after('longitude');
  $table->text('website')->after('roaster');
  $table->text('description')->after('website');
  $table->integer('added_by')->after('description')->unsigned()->nullable();
  $table->foreign('added_by')->references('id')->on('users');
});

The column we are focusing on is the parent column. This is an unsigned integer that’s nullable. Parent cafes, will have no parent so they will be null. Child cafes will reference a parent cafe on the same table.

Quick note, I added a few extra columns to the cafes table which just allows us to save more data. The columns are:

  • location_name -> the name of the location of the cafe
  • roaster -> is the cafe a roaster, do they roast their own beans?
  • website -> website of the cafe
  • description -> paragraph, text, etc to describe the cafe
  • added_by -> references the user that added the cafe

These are nothing I haven’t written about in previous tutorials and you will see references to these fields later on in the tutorial. The only one that might look different is the added_by column which saves a reference to the user that added the cafe.

Step 2: Add Relationships To Cafe Model

In our Cafe.php model, we need to add two relationships. One for the parent and one for the children. A cafe can have many children and only one parent so we need to use the hasMany() and hasOne() relationship types accordingly. Add the following methods to your model:

public function children(){
  return $this->hasMany( 'App\Models\Cafe', 'parent', 'id' );
}

public function parent(){
  return $this->hasOne( 'App\Models\Cafe', 'id', 'parent' );
}

What the children() method does is state that the cafe has many children where the parent column is equal to the id column of the object we are calling the method on. So if we get cafe id 1, we get all of the cafes with the parent id of 1.

What the parent() method defines is that a cafe can only have 1 parent. This grabs the cafe defined by the id in the parent column.

Conclusion

We now have our parent child relationship set up with eloquent! Now we need to adjust our front end to pass some code to our API to save to the database. Saving related models will just require the user to save one model first and save it’s ID to set as the parent. The next tutorial will bind the many to many relationship structure we configured and this relationship together on the front end and we will confirm any validations necessary.

Remember, all code is located: GitHub – serversideup/roastandbrew: Helping the coffee enthusiast find their next cup of coffee. Also, helping aspiring web and mobile app developers build a single page app and converting it to a mobile hybrid. All tutorials can be found at https://serversideup.net and feel free to reach out if you have any questions!