phpmysqllaraveldingo-api

Laravel hasMany error. 'site_id' doesn't have a default value


I have following method in a controller

public function store(Request $request)
{
    $site = Site::create([
        "path" => $request->path,
        "site_link" => $request->link,
    ]);

    if ($request->features) {
        $features = explode(',', $request->features);

        foreach ($features as $feature) {
            $site->features()->save(SiteFeature::create(["feature" => $feature]));
        }
    }

    return response()->json($site, 201);
}

Site model has this method

public function features()
{
    return $this->hasMany('App\SiteFeature');
}

And this is my $fillable property of a SiteFeature

protected $fillable = ['feature', 'site_id'];

By some reason I get next error

local.ERROR: SQLSTATE[HY000]: General error: 1364 Field 'site_id' doesn't have a default value (SQL: insert into site_features (feature) values (fes)) {"exception":"[object] (Illuminate\Database\QueryException(code: HY000): SQLSTATE[HY000]: General error: 1364 Field 'site_id' doesn't have a default value (SQL: insert into site_features (feature) values (fes))


Solution

  • The Model::create method actually creates a record in your database and since you're not specifying a required site_id, it is failing which is why you're seeing this error.

    It looks like you're trying to use Laravel's relationships to save a new SiteFeature for the site but you're passing what would be an already existing object (if the query didn't fail) to the relation's save method.

    You need to either pass a new instance of SiteFeature, that has not already been saved to the database to the save method:

    $this->features()->save(new SiteFeature(['feature' => $feature]));
    

    or you can use the relation's create method to avoid having to pass in an instance altogether, you just need to provide the attributes:

    $this->features()->create(['feature' => $feature]);