Как вытянуть данные из модели через 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 шт):
Ошибка возникает из-за того, что 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');
}