Как вытянуть данные из модели через hasManyThrough в Laravel?

Есть фрагменты моих миграций:

Первая основная таблица:

public function up(): void
{
    Schema::create('test1s', function (Blueprint $table) {
        $table->id();
        $table->string('name');
        $table->string('desc')->nullable();
        $table->timestamps();
    });
}

Вторая таблица:

public function up(): void
{
    Schema::create('test2s', function (Blueprint $table) {
        $table->id();
        $table->string('name');
        $table->string('desc')->nullable();
        $table->foreignId('test2_id')->references('id')->on('test1s')->onDelete('cascade');
        $table->timestamps();
    });
}

Третья таблица:

public function up(): void
{
    Schema::create('test3s', function (Blueprint $table) {
        $table->id();
        $table->string('name');
        $table->string('desc')->nullable();
        $table->foreignId('test3_id')->references('id')->on('test2s')->onDelete('cascade');
        $table->timestamps();
    });
}

На каждую миграцию созданы модели. Создавались файлы миграций через php artisan make:model Test1 -m

Далее в моделе Test1 создаю метод:

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasManyThrough;

class Test1 extends Model
{
    use HasFactory;
    
    public function test1(): HasManyThrough
    {
        return $this->hasManyThrough(Test3::class, Test2::class);
    }
}

После чего через контроллер вызываю это всё:

public function index()
{
    $res = Test1::with('test1')->get();
    return view('home' , compact['res']);
}

Подключив модель: use App\Models\Test1;

Далее в home.blade вызываю {{dd($res)}}


Но у меня ошибка:

SQLSTATE[42S22]: Column not found: 1054 Unknown column 'test2s.test1_id' in 'field list'

И указан SQL-запрос:

select
`test3s`.*,
`test2s`.`test1_id` as `laravel_through_key`
from
`test3s`
inner join `test2s` on `test2s`.`id` = `test3s`.`test2_id`
where
`test2s`.`test1_id` in (1, 2)

Ответы (1 шт):

Автор решения: mydls1

Ошибка возникает из-за того, что Laravel ожидает наличие столбца test1_id в таблице test2s, чтобы связать таблицу test2s с test1s. Это необходимо для метода hasManyThrough, который требует, чтобы в промежуточной таблице (test2s) был внешний ключ, указывающий на родительскую таблицу (test1s). В вашем случае, такого столбца нет, так как в миграции для таблицы test2s был использован столбец test2_id, а не test1_id.

Внимательно прочтите документацию, вам нужно понять как работает это , желательно под капотом.

public function up(): void
{
    Schema::create('test2s', function (Blueprint $table) {
        $table->id();
        $table->string('name');
        $table->string('desc')->nullable();
        $table->foreignId('test1_id')->references('id')->on('test1s')->onDelete('cascade'); // Изменено на test1_id
        $table->timestamps();
    });
}

Затем

php artisan migrate:fresh

Если вы не хотите изменять миграцию, вы можете указать внешний ключ и промежуточный ключ в методе hasManyThrough в модели Test1.

Измените метод test1 в модели Test1 следующим образом:

public function test1(): HasManyThrough
{
    return $this->hasManyThrough(Test3::class, Test2::class, 'test1_id', 'test2_id', 'id', 'id');
}
→ Ссылка