Oranges13
Oranges13

Reputation: 1084

Attach existing record to eloquent hasMany / belongsTo relationship

I have a model SalesArea which hasMany Regions. Regions belongTo one SalesArea.

class SalesArea extends Model
{
    public function regions() {
        return $this->hasMany('App\Region');
    }
}

class Region extends Model
{
    public function sales_area() {
        return $this->belongsTo('App\SalesArea');
    }
}

Due to some changes in organization, the parent (SalesArea) is being created after the Regions have been created. I am trying to associate the Regions with their associated Sales areas when the Sales Area record is created.

I created a migration to add sales_area_id to the regions table, and they are currently all null.

I have a select box that has the various IDs of Regions and I would like to associate the regions with a Sales Area at once with an array of ids. None of the association methods are working.

$area = SalesArea::create($request->all());

$area->regions()->attach([1,2,3]); // BadMethodCallException with message 'Call to undefined method Illuminate\Database\Query\Builder::attach()

$area->regions()->add([1,2,3]); // BadMethodCallException with message 'Call to undefined method Illuminate\Database\Query\Builder::add()'

$area->regions()->sync([1,2,3]); // BadMethodCallException with message 'Call to undefined method Illuminate\Database\Query\Builder::sync()'

$area->regions()->associate([1,2,3]); // BadMethodCallException with message 'Call to undefined method Illuminate\Database\Query\Builder::associate()'

I am stumped on how this is supposed to work. Regions already exist, I just need to add their relationships to their associated sales area.

Upvotes: 4

Views: 9072

Answers (2)

Oranges13
Oranges13

Reputation: 1084

public function store(Request $request)
{
    $this->validate($request, [
       'name' => 'required|unique:sales_areas',
       'regions' => 'required|array',
       'regions.*' => 'int',
    ]);

    $salesArea = SalesArea::create($request->all());

    // Because we have a hasMany not a many to many, we have to do it this way
    Region::whereIn('id', $request->regions)->update(['sales_area_id' => $salesArea->id]);

    flash('Created Sales Area ' . $salesArea->name);
    return redirect()->route('areas.index', $salesArea->id);
}

Upvotes: 2

prateekkathal
prateekkathal

Reputation: 3572

Please ensure you have the column, sales_area_id in your regions table

$salesArea = SalesArea::create($request->all());

$regions = Region::whereIn('id', [1, 2, 3])->get();

$salesArea->regions()->saveMany($regions);

I am not sure, why you are creating the regions this way. If there is a hasMany()relation between SalesArea & Region then all regions should be created like :

$salesArea->regions()->create([ ... ]);

And if your relations are like this

class SalesArea extends Model
{
    public function regions() {
        return $this->belongsToMany(Region::class)->withPivot(['id'])->withTimestamps();
    }
}

class Region extends Model
{
    public function sales_area() {
        return $this->belongsToMany(SalesArea::class)->withPivot(['id'])->withTimestamps(
    }
}

then you can do something like this.

$salesArea = SalesArea::create($request->all());

$regions = Region::whereIn('id', [1, 2, 3])->get();

$salesArea->regions()->sync($regions->pluck('id')->toArray());

Upvotes: 1

Related Questions