Laravel-tips del 5 – model binding med relationer

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:

Schema::create('users', function (Blueprint $table) {
    $table->increments('id');
    $table->string('email')->unique();
    $table->string('password', 60);
    $table->rememberToken();
    $table->timestamps();
});

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

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

    // Relationship
    $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
});

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:

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

Och i controllern:

public function update(Request $request, $id)
{
    $user = User::findOrFail($id);
    $user->email = $request->input('email');
    $user->save();

    $user->userMeta->name = $request->input('name');
    $user->userMeta->phone = $request->input('phone');
    $user->userMeta->save();

    return redirect(route('users.index'));
}

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:

// edit.blade.php
{!! Form::model($user, ['route' => ['users.update', $user->id], 'method' => 'put']) !!}
    {!! Form::label('email', 'E-mail') !!}
    {!! Form::text('email', null) !!}
    {!! Form::label('user_meta[phone]', 'Name') !!}
    {!! Form::text('user_meta[phone]', null) !!}
    {!! Form::label('user_meta[name]', 'Name') !!}
    {!! Form::text('user_meta[name]', null) !!}
{!! Form::close() !!}

// UserController.php
public function update(Request $request, $id)
{
    $user = User::findOrFail($id);
    $user->fill($request->except('user_meta'));
    $user->save();

    $user->userMeta()->save($request->input('user_meta'));

    return redirect(route('users.index'));
}

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.