У меня есть начало Laravel приложения только с двумя моделями: Пользователь и Проект. Между Пользователями и Проектами существует отношение многие ко многим, один Пользователь может работать над многими Проектами, а один Проект может работать со многими Пользователями.
Проблема, с которой я столкнулся, проявилась двумя способами:
- После миграции и заполнения моей БД с основными данными c я вручную создаю строку в сводной таблице
project_user
, связывая ссылки на первые записи * 1007. * и projects
таблицы: INSERT INTO project_user (user_id, project_id) VALUES (1, 1)
. Затем я загружаю Тинкер, чтобы проверить отношения. Доступ ко всем проектам через модель User работает должным образом: User::find(1)->projects
(возвращает действительную коллекцию моделей Project), однако обратное соотношение: Project::find(1)->users
возвращает пустую коллекцию, когда она должна возвращать модель User, указанную в сводной таблице. таблица. - И при использовании файла Seeder для заполнения таблицы
project_user
, например, так:
public function run()
{
$project = Project::first();
$admin = User::first();
if (isset($project) && isset($admin)) {
echo "Project: $project\n";
echo "User: $admin\n";
// FIXME: Why isn't this working?
$project->users()->attach($admin);
// The inverse below also fails for the same reason
// $admin->projects()->attach($project);
}
}
, что приводит к сбою файла заполнения с ошибкой: SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'project_id' cannot be null (SQL: insert into
project_user (
create_at ,
project_id ,
updated_at ,
user_id ) values (2020-02-02 17:01:04, ?, 2020-02-02 17:01:04, 1))
Я искал свой код, а inte rnet ищет решение, но безрезультатно , Проблема должна заключаться в крошечной ошибке в моем коде, неправильном использовании какой-либо функции или неправильном порядке операций. Для меня ясно, что должна быть проблема с ассоциацией на стороне проекта, но я буквально сравнивал пользователей и проекты на каждом шагу, и я не могу понять, в чем дело. Я вставлю соответствующие разделы кода ниже, и если есть какая-либо дополнительная информация или код, который я могу предоставить, я более чем рад это сделать. Заранее благодарим за помощь!
Вот определения модели:
class User extends Authenticatable
{
public $type;
// Here is the relationship to the Projects this User is working on
public function projects()
{
// SELECT * FROM project_user WHERE user_id = $user->id
return $this->belongsToMany(Project::class)->withTimestamps();
}
use Notifiable;
protected $fillable = [
'name', 'email', 'password',
];
protected $hidden = [
'password', 'remember_token',
];
protected $casts = [
'email_verified_at' => 'datetime',
];
}
class Project extends Model
{
public $id;
public $name;
public $deleted_at;
// Here is the relationship to the Users working on this Project
public function users()
{
// SELECT * FROM project_user WHERE project_id = $project->id
return $this->belongsToMany(User::class)
->withTimestamps();
}
protected $fillable = [
'name',
];
protected $casts = [
'deleted_at' => 'datetime',
];
}
Миграции таблиц users
и projects
:
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->string('email')->unique();
$table->enum('type', ['admin', 'client', 'editor'])->default('client');
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
public function up()
{
Schema::create('projects', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name')->unique();
$table->integer('memberCount')->default(0)->nullable(false);
$table->timestamp('deleted_at')->nullable();
$table->timestamps();
});
}
А вот сводная таблица project_user
миграции, которая устанавливает ссылки:
public function up()
{
Schema::create('project_user', function(Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('user_id');
$table->unsignedBigInteger('project_id');
$table->timestamps();
$table->unique(['user_id', 'project_id']);
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->foreign('project_id')->references('id')->on('projects')->onDelete('cascade');
});
}