Database tables are often related to one another. A blog post has many comments; an order belongs to a user. Eloquent makes it easy to define these relationships and query related data in a natural, expressive way.Relationships are defined as methods on your Eloquent model classes.
Examples on this page use User, Post, Comment, and Tag models. Assume these models and their database tables already exist.
<?phpnamespace App\Models;use Illuminate\Database\Eloquent\Model;use Illuminate\Database\Eloquent\Relations\HasOne;class User extends Model{ public function profile(): HasOne { return $this->hasOne(Profile::class); }}
Eloquent assumes the profiles table has a user_id foreign key based on the parent model name.
Access the relationship as a property — Eloquent queries the database automatically:
$user = User::find(1);$profile = $user->profile;
Calling a relationship method as a property is called a “dynamic relationship property”. Eloquent runs the query and returns the result the first time you access it.
<?phpnamespace App\Models;use Illuminate\Database\Eloquent\Model;use Illuminate\Database\Eloquent\Relations\HasMany;class Post extends Model{ public function comments(): HasMany { return $this->hasMany(Comment::class); }}
Eloquent assumes the comments table has a post_id foreign key.
Use a many-to-many relationship when both models can be associated with multiple instances of each other. For example, a Post can have many Tag records, and a Tag can belong to many posts.
<?phpnamespace App\Models;use Illuminate\Database\Eloquent\Model;use Illuminate\Database\Eloquent\Relations\BelongsToMany;class Post extends Model{ public function tags(): BelongsToMany { return $this->belongsToMany(Tag::class); }}
Define the inverse on Tag to navigate in both directions:
<?phpnamespace App\Models;use Illuminate\Database\Eloquent\Model;use Illuminate\Database\Eloquent\Relations\BelongsToMany;class Tag extends Model{ public function posts(): BelongsToMany { return $this->belongsToMany(Post::class); }}
Use attach() to add a record to the pivot table, detach() to remove one:
$post = Post::find(1);// Add a tag$post->tags()->attach($tagId);// Remove a tag$post->tags()->detach($tagId);// Replace all current associations$post->tags()->sync([$tagId1, $tagId2]);
sync() removes any pivot rows not included in the given array and inserts the ones that are missing, leaving you with exactly the specified set of associations.
When you access a relationship as a property, Eloquent runs a separate query each time. Inside a loop this creates an N+1 problem:
// 1 query to retrieve all posts$posts = Post::all();foreach ($posts as $post) { // 1 additional query per post to retrieve its user echo $post->user->name;}
With 100 posts, this runs 101 queries, which has a significant impact on performance.
Use with() to load all related data in just two queries:
// 2 queries total regardless of the number of posts$posts = Post::with('user')->get();foreach ($posts as $post) { // No additional queries echo $post->user->name;}
The two queries are:
select * from postsselect * from users where id in (1, 2, 3, ...)