Laravel-tips del 5 – model binding med relationer

Marcus Olsson,

Ett tips som sparar tid i enklare applikationer som inte kräver mycket manipulation med data som ska sparas i databasen.

Ponera att man har sin vanliga Users-tabell:

1Schema::create('users', function (Blueprint $table) {
2 $table->increments('id');
3 $table->string('email')->unique();
4 $table->string('password', 60);
5 $table->rememberToken();
6 $table->timestamps();
7});
1Schema::create('users', function (Blueprint $table) {
2 $table->increments('id');
3 $table->string('email')->unique();
4 $table->string('password', 60);
5 $table->rememberToken();
6 $table->timestamps();
7});

Och en user_metas-tabell för att spara undan användarnas personliga data:

1Schema::create('user_metas', function (Blueprint $table) {
2 $table->increments('id');
3 $table->integer('user_id')->unsigned();
4 $table->string('name');
5 $table->string('phone');
6 $table->timestamps();
7
8 // Relationship
9 $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
10});
1Schema::create('user_metas', function (Blueprint $table) {
2 $table->increments('id');
3 $table->integer('user_id')->unsigned();
4 $table->string('name');
5 $table->string('phone');
6 $table->timestamps();
7
8 // Relationship
9 $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
10});

Använder man sedan den traditionella Form-helpern (illuminate/html innan Laravel 5, och numera LaravelCollective/html), så ser man väldigt ofta något liknande det här i sin blade-template:

1{!! Form::model($user, ['route' => ['users.update', $user->id], 'method' => 'put']) !!}
2 {!! Form::label('email', 'E-mail') !!}
3 {!! Form::text('email', null) !!}
4 {!! Form::label('name', 'Name') !!}
5 {!! Form::text('name', null) !!}
6 {!! Form::label('phone', 'Telephone') !!}
7 {!! Form::text('phone', null) !!}
8{!! Form::close() !!}
1{!! Form::model($user, ['route' => ['users.update', $user->id], 'method' => 'put']) !!}
2 {!! Form::label('email', 'E-mail') !!}
3 {!! Form::text('email', null) !!}
4 {!! Form::label('name', 'Name') !!}
5 {!! Form::text('name', null) !!}
6 {!! Form::label('phone', 'Telephone') !!}
7 {!! Form::text('phone', null) !!}
8{!! Form::close() !!}

Och i controllern:

1public function update(Request $request, $id)
2{
3 $user = User::findOrFail($id);
4 $user->email = $request->input('email');
5 $user->save();
6
7 $user->userMeta->name = $request->input('name');
8 $user->userMeta->phone = $request->input('phone');
9 $user->userMeta->save();
10
11 return redirect(route('users.index'));
12}
1public function update(Request $request, $id)
2{
3 $user = User::findOrFail($id);
4 $user->email = $request->input('email');
5 $user->save();
6
7 $user->userMeta->name = $request->input('name');
8 $user->userMeta->phone = $request->input('phone');
9 $user->userMeta->save();
10
11 return redirect(route('users.index'));
12}

Men – om man nu vill göra det snabbt och enkelt, så är det bra att känna till att man enkelt kan kombinera model-binding tillsammans med sin data betydligt smidigare:

1// edit.blade.php
2{!! Form::model($user, ['route' => ['users.update', $user->id], 'method' => 'put']) !!}
3 {!! Form::label('email', 'E-mail') !!}
4 {!! Form::text('email', null) !!}
5 {!! Form::label('user_meta[phone]', 'Name') !!}
6 {!! Form::text('user_meta[phone]', null) !!}
7 {!! Form::label('user_meta[name]', 'Name') !!}
8 {!! Form::text('user_meta[name]', null) !!}
9{!! Form::close() !!}
10
11// UserController.php
12public function update(Request $request, $id)
13{
14 $user = User::findOrFail($id);
15 $user->fill($request->except('user_meta'));
16 $user->save();
17
18 $user->userMeta()->save($request->input('user_meta'));
19
20 return redirect(route('users.index'));
21}
1// edit.blade.php
2{!! Form::model($user, ['route' => ['users.update', $user->id], 'method' => 'put']) !!}
3 {!! Form::label('email', 'E-mail') !!}
4 {!! Form::text('email', null) !!}
5 {!! Form::label('user_meta[phone]', 'Name') !!}
6 {!! Form::text('user_meta[phone]', null) !!}
7 {!! Form::label('user_meta[name]', 'Name') !!}
8 {!! Form::text('user_meta[name]', null) !!}
9{!! Form::close() !!}
10
11// UserController.php
12public function update(Request $request, $id)
13{
14 $user = User::findOrFail($id);
15 $user->fill($request->except('user_meta'));
16 $user->save();
17
18 $user->userMeta()->save($request->input('user_meta'));
19
20 return redirect(route('users.index'));
21}

Se till att sätta $guarded till [] eller liknande om du vill använda dig av fill().

Ju fler fält det rör sig, destå mer kod tjänar man på den här metoden.