Laravel 外键未按预期工作

问题描述 投票:0回答:1

我在使用 Laravel 的外键时遇到了问题。每个用户都有自己的帖子,因此当用户登录时,他可以管理他的帖子(编辑或删除它们)。当登录用户创建帖子时,它会存储在 posts 表中,并使用包含当前登录用户 ID 的外键“user_id”。 用户表:

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('users', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('role')->nullable();
            $table->integer('times_donated')->default(0);
            $table->string('email')->unique();
            $table->longText('description')->nullable();
            $table->string('profile_picture')->nullable();
            $table->string('background_picture')->nullable();
            $table->timestamp('email_verified_at')->nullable();
            $table->string('password');
            $table->rememberToken();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('users');
    }
};

帖子表:

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->id();
            $table->foreignId('user_id')->nullable()->constrained()->onDelete('cascade');
            $table->string('username');
            $table->string('blood_type');
            $table->string('status');
            $table->string('contact_info');
            $table->longText('description');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('posts');
    }
};

用户型号:

<?php

namespace App\Models;

// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;

class User extends Authenticatable
{
    use HasApiTokens, HasFactory, Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array<int, string>
     */
    protected $fillable = [
        'name',
        'email',
        'password',
        'description',
        'role',
    ];

    /**
     * The attributes that should be hidden for serialization.
     *
     * @var array<int, string>
     */
    protected $hidden = [
        'password',
        'remember_token',
    ];

    /**
     * The attributes that should be cast.
     *
     * @var array<string, string>
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
        'password' => 'hashed',
    ];

    // relationship with posts
    public function posts(){
        return $this->hasMany(Post::class, 'user_id');
    }
}

帖子模型:

<?php

namespace App\Models;

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

class Post extends Model
{
    use HasFactory;

    // relationship to user
    public function user(){
        return $this->belongsTo(User::class, 'user_id');
    }
}

创建帖子导致此控制器方法:

// store post data
    public function store(PostRequest $request){
        $formFields = $request->validated();
        $formFields['user_id'] = Auth::id();
        
        Post::create($formFields);
    }

API路线:

// create post
Route::post('/posts', [PostController::class, 'store']);

我是 Laravel 的初学者,自从我关注 YouTube 教程以来就期待它能够工作。当我创建帖子时,它成功添加到帖子表中,但“user_id”= null。我认为这与外键上的可为空属性有关,因为在教程中他没有向外键添加可为空并且它有效,但是当我这样做时它给出了一个错误(一般错误:1364 Field 'user_id ' 没有默认值)。

laravel foreign-keys
1个回答
0
投票

您需要将 user_id 添加到 Post Model 中的 fillable 中才能批量分配

protected $fillable = [
'user_id',
'username',
'blood_type',
'status',
'contact_info',
'description'
];

如果不添加它,每列都会采用数据库默认值

也不要忘记将身份验证中间件添加到路由中

Route::post('/posts', [PostController::class, 'store'])
->middleware(['auth:sanctum']);

否则

Auth::id()
也会返回null

© www.soinside.com 2019 - 2024. All rights reserved.