Laravel Has Many Through es un tipo de relación que nos permite acceder a datos alejados de nuestro modelo.
Una relación distante en Laravel puede ser aquella entre un modelo User, Country y Posts, ¿cómo harías para obtener todos los posts de España? Este tipo de relaciones en Eloquent se conocen como Has Many Through, y sirven para tener acceso rápido y sin complejas configuraciones a modelos lejanos.
Vamos a crear un rápido ejemplo utilizando los 3 modelos comentados anteriormente, User, Country y Posts, así que crea primero las migraciones necesarias con la siguiente estructura.
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateCountriesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('countries', function (Blueprint $table) {
$table->id();
$table->string("name");
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('countries');
}
}
class CreateUsersTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->foreignId("country_id")->constrained();
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('users');
}
}
class CreatePostsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->foreignId("user_id")->constrained();
$table->string("title");
$table->integer("points")->default(0);
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('posts');
}
}
Ahora abre cada uno de sus modelos y haz las siguientes modificaciones para establecer las relaciones necesarias.
Country.php
<?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;
public function posts(): HasManyThrough {
return $this->hasManyThrough(
Post::class,
User::class,
'country_id',
'user_id',
'id',
'id',
);
}
}Post.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class Post extends Model
{
use HasFactory;
public function user(): BelongsTo {
return $this->belongsTo(User::class);
}
}User.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
use HasFactory, Notifiable;
public function posts(): HasMany {
return $this->hasMany(Post::class);
}
public function country(): BelongsTo {
return $this->belongsTo(Country::class);
}
}
Con lo anterior, ya tenemos modificados todos los modelos para que las relaciones de largo alcance Has Many Through en Laravel funcionen perfectamente, sólo nos queda utilizarlo.
<?php
use App\Models\Country;
use Illuminate\Support\Facades\Route;
Route::get('/through', function () {
$spainPosts = Country::with(["posts:user_id,title", "posts.user:id,name,country_id"])->whereName("Spain")->first();
dd($spainPosts->posts);
});
Curso Laravel 12
Completo 2026
El único curso 100% actualizado que incluye Laravel 12, Livewire 3, Vue 3, React 19 e Inertia 2. Aprende con proyectos reales y las últimas funcionalidades.
star Incluido en cualquier suscripción