confm
confm

Reputation: 297

Laravel - Many to Many - Model binding

I need some help.

I have these tables: users, buys and codecs. I have a many-to-many relationship: buys, codecs, buy_codec

Tables

Schema::create('codecs', function (Blueprint $table) {
    $table->increments('id');
    $table->string('name');
    $table->timestamps();
});

Schema::create('buys', function (Blueprint $table) {
    $table->increments('id');
    $table->integer('user_id')->unsigned();
    $table->string('name');
});   

Schema::create('buy_codec', function (Blueprint $table) {
    $table->increments('id');
    $table->integer('buy_id')->unsigned();
    $table->foreign('buy_id')->references('id')->on('buys')->onDelete('cascade');

    $table->integer('codec_id')->unsigned();
    $table->foreign('codec_id')->references('id')->on('codecs')->onDelete('cascade');

    $table->timestamps();
}); 

This is my controller:

   class UserBuyController extends Controller
{
    public function create($userId)
    {
        $codecs = Codec::lists('name', 'id');
        $usr = User::findOrFail($userId);
        return view('buy.create', compact('usr', 'codecs'));
    }

    public function store($userId, Request $request)
    {
        $codecs = $request->input('codecs');
        $usr = User::findOrFail($userId)->buy()->create($request->except('codecs'));
        $usr->codec()->sync($codecs);
        return redirect('user/'.$userId.'/buy');
    }

    public function edit($userId, $id)
    {
        $codecs = Codec::lists('name', 'id');
        $buy = User::findOrFail($userId)->buy()->findOrFail($id);
        return view('buy.edit', compact('buy', 'codecs'));
    }
}

Create form

{!! Form::open(['method'=>'POST', 'action'=>['UserBuyController@store', $usr->id]]) !!}

    <div class="form-group">
        {!! Form::label('name', 'Name:') !!}
        <div class="input-group">
            <span class="input-group-addon"><i class="fa fa-font"></i></span>
            {!! Form::text('name', null, ['class'=>'form-control']) !!}
        </div>
    </div>

    <div class="form-group">
        {!! Form::label('codecs', 'Outbound Codecs:') !!}
        <div class="input-group">
            <span class="input-group-addon"><i class="fa fa-language"></i></span>
            {!! Form::select('codecs[]', $codecs, null, ['class'=>'form-control', 'multiple'=>true]) !!}
        </div>
    </div>

    {!! Form::submit('Submit', ['class'=>'btn btn-info']) !!}

{!! Form::close() !!}

And this is the edit form

  {!! Form::model($buy,['url'=>url('user/'.$buy->user->id.'/buy/'.$buy->id),'method'=>'patch']) !!}

    <div class="form-group">
        {!! Form::label('name', 'Name:') !!}
        <div class="input-group">
            <span class="input-group-addon"><i class="fa fa-font"></i></span>
            {!! Form::text('name', null, ['class'=>'form-control']) !!}
        </div>
    </div>

    <div class="form-group">
        {!! Form::label('codecs', 'Outbound Codecs:') !!}
        <div class="input-group">
            <span class="input-group-addon"><i class="fa fa-language"></i></span>
            {!! Form::select('codecs[]', $codecs, null, ['class'=>'form-control', 'multiple'=>true]) !!}
        </div>
    </div>

    {!! Form::submit('Update', ['class'=>'btn btn-info']) !!}

{!! Form::close() !!}

Model binding doesn't work

Something is wrong but I don't know what.

This is my pivot table. I have 2 codecs associated with buy_id 3

enter image description here

And this is my edit page.

enter image description here

Nothing is selected.


Update

Model

class Buy extends Model
{
    protected $guarded = ['id'];
    public function codec() {
        return $this->belongsToMany('App\Codec');
    }
    public function user() {
        return $this->belongsTo('App\User');
    }
}

class Codec extends Model
{
    protected $guarded = ['id'];
    public function buy() {
        return $this->belongsToMany('App\Buy');
    }
}
class User extends Authenticatable
{
    public function buy() {
        return $this->hasMany('App\Buy');
    }
}

Upvotes: 1

Views: 152

Answers (2)

hakany
hakany

Reputation: 7264

in the edit form: {!! Form::select('codecs[]', $codecs, null, ['class'=>'form-control', 'multiple'=>true]) !!} the default selected value is set as null. You should set here the list of ids of the associated codecs.

Hope this helps.

Upvotes: 1

Rwd
Rwd

Reputation: 35200

One solution would be to create an accessor for the codec ids and use that with Form::select() instead:

In your Buy model add the following accessor:

public function getCodecListAttribute()
{
    return $this->codecs->pluck('id')->toArray();
}

Then change you select block to:

<div class="form-group">
    {!! Form::label('codec_list', 'Outbound Codecs:') !!}
    <div class="input-group">
        <span class="input-group-addon"><i class="fa fa-language"></i></span>
        {!! Form::select('codec_list[]', $codecs, null, ['class'=>'form-control', 'multiple'=>true]) !!}
    </div>
</div>

This will mean that when you try to get the value from the request you will have to use codec_list instead of codecs.

Hope this helps!

Upvotes: 1

Related Questions