DEV Community

Cover image for Laravel101: Exploring Entity-Model Relationships
Kazem
Kazem

Posted on • Edited on

Laravel101: Exploring Entity-Model Relationships

Up until now, we’ve built an awesome app that lets users save tasks. But now, we want to take it a step further and save each user’s tasks individually. That means each user will have their own set of tasks. And of course, we’ll make sure to relate the tasks with the current user who’s logged into the app. So, they’ll have easy access to the their tasks. Sounds cool, right?


Relational Database Management Systems (RDBMS) are a type of database management system that work based on relationships. Basically, data and relationships are organized using a set of related tables. Many popular DBMSs like SQLite, MySQL, and Microsoft Access follow this structure.

Now, talking about different types of database management structures is beyond the scope of this article. However, if you’re curious and want to explore more about the various types of DBMS, you can check out the following link:

Types of Databases

There are multiple types of databases, such as relational database management systems, object databases, graph databases, network databases, and document db. In this article, we discuss the types of Database Management Systems or DBMS.

c-sharpcorner.com

Alright, let’s dive into the topic of defining relationships in models.

When it comes to table relationships, the main ones we encounter are one-to-many and one-to-one. In a one-to-one relationship, each record in one table is linked to just one record in another table. For instance, think of the connection between a student’s and their account details:

Image description

On the other hand, in a one-to-many relationship, each record in one table can be associated with multiple records in another table. Take a peek at the image below:

Image description

you’ll notice that each customer can have several orders, but each order belongs to only one customer.

And hey, let’s not forget about another type of relationship called many-to-many. To handle this, we convert it into two one-to-many relationships using an interface table. Check out the image below:

Image description

you’ll see a many-to-many relationship between the courses and students tables, which we’ve transformed using an interface table with two one-to-many relationships.

In our example, each user is associated with their own set of tasks.

Here’s how it works: a user can have multiple tasks, but each task belongs to only one user. So, to make this happen, we need to update our tasks model migration file and introduce a new attribute called foreignId. This attribute will be responsible for storing connection between a user to the task.

To establish this connection, we can use any unique data from users table. In our design, we have options like email and ID.

Here’s a helpful tip: in relational databases, we often use the ID since it optimized retrieval of related models.

Let’s update our migration file and add foreignId :

Schema::create('tasks', function (Blueprint $table) {
    $table->id();
    $table->string('title');
    $table->text('description')->nullable();
    $table->foreignId('user_id')->constrained();
    $table->timestamp('expired_at')->nullable();
    $table->timestamps();
});
Enter fullscreen mode Exit fullscreen mode

As you might have noticed, I’ve used a handy function called constrained here. Its main purpose is to establish a relationship between models in a table. This function adds extra information to attributes, such as the related model’s table name. In this case, the related model is the users table.

You can actually specify the table name explicitly like constrained('users') but this function is smart enough to figure it out automatically based on the foreignId attribute name.

Now we update our migration file let update our tables:

php artisan migrate:fresh --force
Enter fullscreen mode Exit fullscreen mode

Well done! Now, let’s talk about how we can actually use this in our project.

In Laravel, Eloquent provides some handy helper functions to define relationships. In our case, since the task model belongs to a user, we can simply define the belongsTo function in tasks model:

class Task extends Model
{
    public function user()
    {
        return $this->belongsTo(User::class);
    }
}
Enter fullscreen mode Exit fullscreen mode

On the other hand, for our user, which can have many tasks, we can use the hasMany function:

class User extends Authenticatable
{
    public function tasks()
    {
        return $this->hasMany(Task::class);
    }
}
Enter fullscreen mode Exit fullscreen mode

Of course we doesn’t have many-to-many in our project yet, but let’s talk about this exciting relationship. The good news is that it’s simpler for both models! We only need to use the belongsToMany function for both of them. These functions are usually all we need to define relationships. But if you’re looking for more detailed explanations, you can find them right here:

Eloquent: Relationships - Laravel 10.x - The PHP Framework For Web Artisans

Laravel is a PHP web application framework with expressive, elegant syntax. We’ve already laid the foundation — freeing you to create without sweating the small things.

favicon laravel.com

These functions have some really handy applications. Let’s say we have a task and we want to know the name of the user who created it. In this case, here’s how we can tackle it:

$task = Task::find(1);
$task->user->name;
Enter fullscreen mode Exit fullscreen mode

Here’s the thing you should know: In our Task model, we’ve got this cool function called “user” defined. Now, you might be wondering why we’re using it as an attribute, without those parentheses.

Well, let me explain. When we treat these functions as attributes, it’s almost like we’re directly referring to the user model itself using a query. That’s why we can easily access attributes like the user’s name. It’s a convenient way to get the information we need right away!

Let’s practice it with tasks function:

Image description

As you see in above pic you can find all the relevant models for a specific user or perform any query on the task models that are associated with that particular user.


Now, let’s back to our task controller and update the store function. The goal is to create a new task for the current user and set the user ID attribute. We can achieve this in a very direct way with the following code: (auth()->id() get current logged in user id):

$task = new Task();
$task->title = request('title');
$task->descripton = request('descripton');
$task->expired_at = request('expired_at');
$task->user_id = auth()->id();
$task->save();
Enter fullscreen mode Exit fullscreen mode

However, let me introduce you to an even cooler option using the tasks function. This approach offers some amazing benefits. Check it out:

public function store(StoreTaskRequest $request)
{
    auth()->user()->tasks()->create($request->validated());
    return redirect("/tasks", 201);
}
Enter fullscreen mode Exit fullscreen mode

Here the foreign id of user is handled by tasks

That’s awesome! Now, let’s update our index function to retrieve all the tasks associated with the currently logged-in user. It’s really simple. Just update the index function like this:

public function index()
{
    return view('tasks.index', ['tasks' => auth()->user()->tasks]);
}
Enter fullscreen mode Exit fullscreen mode

Also we can make use of the auth functions in Blade templates to directly access the tasks of the current user. This means we can remove the task variable passing from the index function. Instead, we can fetch all the tasks within the Blade template itself. It’s super convenient!

Image description


In this article, we’ve covered the relationships between users and tasks models in Laravel. The information we discussed is not only important but also highly practical. Mastering complex queries is a key skill for anyone working in the backend. I hope you found this tutorial enjoyable and insightful.

Top comments (0)