Laravel hasMany save
Asked Answered
S

3

5

I've two tables to save data to. One of them has foreign key so that I have one-to-many relationship. However, I don't understand how to save data into two table simultaneously. I have one query which contains data for one table and for another that should be attached to first one.

That is the main model

class Site extends Model
{
    protected $fillable = ['path', 'site_link'];

    public $timestamps = false;

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

And this is the sub-model

class SiteFeature extends Model
{
    protected $fillable = ['feature', 'site_id'];

    public $timestamps = false;
}

Right now my controller looks like this

class SiteController extends BaseController
{
    public function index()
    {
        return Site::all();
    }

    public function show(Site $id)
    {
        return $this->response->item($id, new SiteTransformer);
    }

    public function store(Request $request)
    {
        $site = Site::create($request->all());

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

I know that it would save it as one piece of data. And I ask you for help me to split data into two tables. In docs I've found the way to store with relationship to an existing model in DB, however I don't have that model at the moment of creation.

Stemma answered 26/8, 2018 at 12:13 Comment(3)
you may wish to use many to many relationship. You can create tables named features, sites and feature_site (pivot). Then all you have to do is sync them..Tucana
What does your migration look like, your migration has to be properly set up aswellKellikellia
Is your $request form returning SiteFeature feature(s) to store() at the same time?Eph
S
7

Solved that way

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

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

        return response()->json($site, 201);
    }
Stemma answered 27/8, 2018 at 4:56 Comment(0)
C
1

It's the correct way to save data using hasMany relationship without creating a new object of lookup model.

       // inside controller
        public function store(Request $request)
        {
            $student = Student::create([
                "name" => $request->get('name'),
                "email" => $request->get('email'),
            ]);

            foreach ($request->subjects as $subject) {
                $student->subjects()->create(["title" => $subject['title']);
            }

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


      // inside User model
       public function subjects()
       {
          return $this->hasMany('App\Models\Subject');
       }     
Carricarriage answered 30/8, 2019 at 18:19 Comment(0)
U
0

There are certain things you have to make sure of.

First: In your SiteFeature-Model the inverse relation to the Site-Models seems to be missing. There should be a function like:

public function site() 
{
    return $this->belongsTo('App\Site');
}

See Laravel 5.6 - Eloquent Relationships, One-to-Many for this.

If however you have a relationship where (n) Sites can be related to (n) SiteFeatures, your relations and inverse relations have to be different. (And there will also have to be a pivot table, in which you can store the n-to-n relation)

See Laravel 5.6 - Eloquent Relationships, Many-to-Many in that case.

Since your Question does not describe what is received with $request, here's what you should consider:

  1. Validate your inputs. This will make sure you don't save garbage to your database
  2. Check if you already have some part of the data-set you want to save, then save in two steps:

First step:

$site = Site::firstOrCreate(['path' => $request['input_name_for_path'],
                             'site_link' => $request['input_name_for_site_link'],
                           ]);

This will give you a proper Site-Model saved to the database. (Note, that this shows how you manually assign values to the fillable fields defined in the model in case you have different input field names)

Now you can go on an save the SiteFeature-Model connected to it:

$feature = SiteFeature::firstOrCreate('feature' => $request['input_name_for_feature');
$site->features()->attach($feature->id);

This should do the trick saving both, a new (or old) Site and a related SiteFeature to your database.

If I misunderstood the question, feel free to add information and I will update.

Undersecretary answered 26/8, 2018 at 13:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.