Exploring Has Many Through Relationships in Laravel 11

Apr 20, 2024 | Laravel 11 Laravel


Hello Dev,

In this tutorial, we'll explore how to implement the "Has Many Through" relationship in a Laravel 11 application using the `hasManyThrough()` method.

In Laravel, the "Has Many Through" relationship facilitates accessing distant relationships. Let's consider a scenario with three tables: "users," "posts," and "countries." Each user can have multiple posts, and each post is associated with a country. With the "Has Many Through" relationship, we can directly access posts belonging to a specific country. This simplifies querying and enables smooth traversal across multiple interconnected tables.

To establish this relationship, we'll utilize the `hasManyThrough()` method, enabling efficient navigation through related data.

Step 1: Generate Migrations

First, ensure you have the users and roles tables in your database. If not, you can create them using migrations. Additionally, you'll need a pivot table to manage the many-to-many relationship. By convention, Laravel uses the singular names of the two related tables, in alphabetical order, separated by an underscore.

php artisan make:migration create_users_table
php artisan make:migration create_posts_table
php artisan make:migration create_countries_table
Read Also: implementing many-to-many relationships in laravel 11 Step 2: Define the Schema for the Tables

In the create_users_table migration, define the schema for the "users" table, including a foreign key country_id that references the "countries" table.

users table migration:
<?php
  
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
  
return new class extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up(): void
    {
        Schema::create('users', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('email')->unique();
            $table->timestamp('email_verified_at')->nullable();
            $table->foreignId('country_id')->constrained('countries');
            $table->string('password');
            $table->rememberToken();
            $table->timestamps();
        });
    }
  
    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down(): void
    {
        Schema::dropIfExists('users');
    }
};

Similarly, define the schemas for the "posts" and "countries" tables, ensuring the "posts" table has a foreign key user_id that references the "users" table.

posts table migration:
<?php
  
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
  
return new class extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up(): void
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->increments('id');
            $table->string("name");
            $table->foreignId('user_id')->constrained('users');
            $table->timestamps();
        });
    }
  
    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down(): void
    {
        Schema::dropIfExists('posts');
    }
};
countries table migration:
<?php
  
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
  
return new class extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up(): void
    {
        Schema::create('countries', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
            $table->timestamps();
        });
    }
  
    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down(): void
    {
        Schema::dropIfExists('countries');
    }
};
Read Also: implementing one-to-many relationships in laravel 11 Step 3: Define the Has Many Through Relationship

In the Country model, define the posts method using the hasManyThrough method to establish the "Has Many Through" relationship.

User Model:
<?php
  
namespace App\Models;
  
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
  
class Country extends Model
{
    use HasFactory;

    /**
     * Write code on Method
     *
     * @return response()
     */
    public function posts(): HasManyThrough
    {
        return $this->hasManyThrough(
            Post::class,
            User::class,
            'country_id', /* Foreign key on users table... */
            'user_id', /* Foreign key on posts table... */
            'id', /* Local key on countries table... */
            'id' /* Local key on users table... */
        );
    }
}
Step 4: Accessing Related Models

With the relationship defined, you can now easily access posts for a specific country.

<?php
  
namespace App\Http\Controllers;
  
use Illuminate\Http\Request;
use App\Models\Country;
  
class UserController extends Controller
{
    /**
     * Write code on Method
     *
     * @return response()
     */
    public function index(Request $request)
    {
        $country = Country::find(1); // Find a country by its ID
        $posts = $country->posts; // Access the posts for the country
        dd($posts);
    }
}

This setup allows you to directly access posts from a country, simplifying queries and enabling seamless navigation through multiple related tables in your Laravel 11 application

Thank you for your encouragement! If you have any questions or need further assistance, feel free to ask. I'm here to help!



Tags :
#Laravel 11
#Laravel
ItErrorSolution.com

ItErrorSolution.com

"Hey there! I'm a full-stack developer and proud owner of ItErrorSolution.com, based right here in India. I love nothing more than sharing handy tips and tricks with my fellow developers through easy-to-follow tutorials. When it comes to coding, I'm all about PHP, Laravel, Angular, Vue, Node, JavaScript, jQuery, CodeIgniter, and Bootstrap – been hooked on them forever! I'm all about putting in the work and staying committed. Ready to join me on this journey to coding?"