Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

keithmichelson's avatar

Form Model Binding with Multiple Models

I made a form that uses 2 models to submit to 2 tables. Now I'm making an edit/update form. Is there a way use 2 models so I can populate the second model field values?

{!! Form::model($article, ['method' => 'PATCH', 'action' => ['ArticlesController@update', $article->id]]) !!}

I have no idea about the syntax but 2 models like this.

{!! Form::model($article, $module, ['method' => 'PATCH', 'action' => ['ArticlesController@update', $article->id]]) !!}

Thanks for any help.

Keith

0 likes
26 replies
sabuncuserhat's avatar

you cannot do by that way.

you can do

public function update($article_id)
{
    $inputData = Input::except("_token");
    Model::find($article_id)->update($inputData);
    Model2::find($article_id)->update($inputData);
    Model3::find($article_id)->update($inputData);


}

keithmichelson's avatar

Thanks for the replies. @martinbean Sorry, I didn't explain it that well and I'm new to this as you can tell.

I have made 1 form that submits data to 2 tables using 2 models. I want to then be able to re-populate that form on an edit page. I've done that using form model binding so far but the only the 1st model populates back into the fields, i'm not sure if it's possible to populate the 2nd model fields as well.

Maybe this will help, see how the "test" gets populated back in the fields when editing? I need to do that for the bottom part under Main Module http://pilotsmedia.com/form-example.jpg

Mattiman's avatar
Level 7

In one of my projects I have a form submitting to 4 models. Binding and populating the fields I do like:

            <div class="form-group">
                {!! Form::label('date', 'Climb date', ['class' => 'control-label']) !!}
                {!! Form::text('date', null, array( 'class'=>'form-control', 'placeholder'=>'yyyy-mm-dd')) !!}
            </div>
            <div class="form-group">
                {!! Form::label('Route name') !!}
                {!! Form::text('name', ( isset($climb->route->name) ? $climb->route->name : null ), array('class'=>'form-control' )) !!}
            </div>
            <div class="form-group">
                {!! Form::label('Area') !!}
                {!! Form::text('area', isset($climb->route->area->name) ? $climb->route->area->name : null, array( 'class'=>'form-control' )) !!}
            </div>

So as you can see, Climb is the first model. A climb is related to a Route, the second model (a climb of a route, so a climb belongs to a route, a route hasMany climbs). A Route belongs to an Area. And lastly (not shown above), an area belongs to a country.

The code above only works if you have set up the relations in the models.

4 likes
keithmichelson's avatar

Hey, @Mattiman thanks for the reply. I have the form doing something similar to what you are doing but are you able to then edit those fields after a submission with how you have it set up? That is where I'm having the big problem.

sukonovs's avatar

Model binding does not work with two models. There will be need to add third parameter to forms fields.

1 like
keithmichelson's avatar

@Mattiman I haven't been able to try yours yet just wanted to make sure. My setup is a little different.

In my article model I have

public function module() {
    return $this->hasMany('App\Module');

}

In my module model I have:

public function articles() {
    return $this->belongsTo('App\Article');

}

and I have this in my module Migration

public function up()
{
    Schema::create('module', function(Blueprint $table)
    {
        $table->increments('id');
        $table->string('heading');
        $table->text('body');
        $table->integer('article_id')->unsigned();
        $table->timestamps();


        $table->foreign('article_id')
              ->references('id')
              ->on('articles')
              ->onDelete('cascade');
    });
}

The basic idea is I have a main article and I want to add multiple modules to it.

keithmichelson's avatar

Okay, I finally grasped what you were talking about @Mattiman, I was over complicating it and what you had worked great. The edit page populates the fields correctly. Now I just can't quite get it to update. Trying what you have @sukonovs but I can't quite get it to work.

<div class="form-group">
    {!! Form::label('heading', 'Heading:') !!}
    {!! Form::text('heading', ( isset($module->heading) ? $module->heading : null ), ['class' => 'form-control']) !!}
</div>

<div class="form-group">
    {!! Form::label('body', 'Body:') !!}
    {!! Form::text('modbod', ( isset($module->body) ? $module->body : null ), array('class'=>'form-control' )) !!}
</div>

Thanks for all the help.

Mattiman's avatar

@keithmichelson that's good to hear it works with the form now.

So what is not working with the update? You mean in the controller method, saving the models to the db? I use a repository class for that, which talks to the different models and saves/updates them correctly. So I pass the request data to the Climb repo, the Climb repo saves the climb model data, the route model data (using a RouteRepo) and the area model data (using an AreaRepo).

sukonovs's avatar

@keithmichelson Do you really need those issets? If $module is Eloquent instance on nonexisting values null will returned anyway.

martinbean's avatar

@keithmichelson If the models are related, you can access the related data like an array:

{!! Form::text('foo', null, ['class' => 'form-control']) !!}

{!! Form::text('relation[foo]', null, ['class' => 'form-control']) !!}
2 likes
keithmichelson's avatar

@Mattiman Yeah the update in the controller method. For the Article model i'm using,

public function update(Article $article, ArticleRequest $request) {

    $article->update($request->all());

    return redirect('articles');
}

I used a RouteServiceProvider that I saw being used in the laracast video. But now for the Module model I'm not really sure how to update that.

keithmichelson's avatar

@Mattiman They are related, hopefully I set that up right. The module table has an article_id field that gets set on creation. I'm not quite following the relation[foo] part. I'm not sure what I would put there.

keithmichelson's avatar

I can update them like this, but I'd like to do it all at once like I'm doing with the Article model. I just don't know how to add the correct syntax.

  public function update(Article $article, ArticleRequest $request) {

    $module = Module::where('article_id', '=', $article->id)->firstOrFail();

    $module->heading = Input::get('heading');

    $module->body = Input::get('modbod');

    $module->save();



    $article->update($request->all());

    return redirect('articles');
}
Mattiman's avatar

You could create an ArticleRepository with a save method, pass it the request data and let that method handle everything?

JarekTkaczyk's avatar

@keithmichelson I guess this is Article hasOne Module relation, so all you need is:

// controller (repo or whatever)
$article = Article::with('module')->find($someId); // eager load the relation

// view
Form::model($article ...)
Form::text('module[name]') // assuming $module->name

It will work only for x-1 relations (hasOne, morphTo, belongsTo, morphOne). For x-m relations you need to do it manually obviously, but that's not a problem either.

2 likes
keithmichelson's avatar

@JarekTkaczyk Thanks for the reply. My Article is a hasMany relation to the Module since it will have many of those on 1 article page and the Module is a belongsTo Article relation. Do you see anything wrong with what I'm doing in the above?

@Mattiman I'm not sure what those are but I will look that up. Thanks.

keithmichelson's avatar

@JarekTkaczyk Sorry I didn't quite mean wrong, just best practice. It's doing what I want it to and it's a x-m relation so I have to do it manually like you said.

Thanks for the help.

Swaz's avatar

@keithmichelson I'm a little late to the party, but you can do what you want like this:

Form::model($article->toArray() + $module->toArray(), ['method' => 'PATCH'])
4 likes
keithmichelson's avatar

@Swaz: Thanks for posting that, I haven't messed with the code for awhile but I'll try and check that out, it would save me a lot of lines of code.

kwiz's avatar

@JarekTkaczyk Your reply really helped me, but I am having trouble updating the model.

Using your example:

// controller (repo or whatever)
$article = Article::with('module')->find($someId); // eager load the relation

// view
Form::model($article ...)
Form::text('module[name]') // assuming $module->name

How would you do an update? Here I what I have, it updates the Article but not the Module.

public function update(Request $request, $someId)
{
    $article = Article::with('module')->find($someId); 
    $article->update($request->all());
}
JarekTkaczyk's avatar

@kwiz all you need is this (assuming you use fillable on your models, and you should most likely):

$article->update($request->all());
$article->module->update($request->get('module'));

Above is the simplest possible code that will work. It requires a bit of validation etc, but you should be fine with that part.

happy coding!

1 like

Please or to participate in this conversation.