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

Spencer's avatar

Form Model Binding - Database fields and form inputs have different names

Working on a project that includes an old database that has too many dependencies to ever change names for the fields. But in my new code I'd like to refer to the fields and hence names of the form input fields by different names that are more standard. The problem with this is that the automatic Laravel form model binding then has no idea where to put the values from the fields.

I was sure that there was better documentation on this, but currently this is all I can find. https://laravelcollective.com/docs/5.2/html#form-model-binding

So here would be an example of the problem:

An Order table that has fields such as 'first_name', 'last_name', 'cell', 'cc_number', 'billing_schedule', etc.

And a new order form that has input names such as 'full_name', 'cell_phone', 'credit_card_number', 'annual_monthly', etc.

So when I have these conflicting names and I use:

   {!!Form::model($order,['action' => 'order@update'])!!}

Any form input names that don't match their corresponding database field names are left blank when editing the form.

Is there any way to alter the Order model to allow for this discrepancy? I know I can edit the Order model to match up with a different table just by setting the protected $table variable. Just wondering if there was some similar approach to fixing this problem.

0 likes
14 replies
jekinney's avatar

Somewhere along the line you need to then transform the data. On the view maybe not the best place (meaning name and value not matching). Probably best somewhere else. As then it'll be less confusing, reusable and in one spot.

Map your data from the database to the new variable names and back again.

Not to common but common enough that there are packages and patterns for it.

Also, I bet if you used HTML you probably be done by now?

Spencer's avatar

Do you know of any documentation that points to those packages or patterns?

And what do you mean if I used HTML I'd be done by now?... HTML is not a logic based language so it couldn't handle any auto-population of the input values from a database.

Snapey's avatar

Accessors and mutators?

You can give the model the new names and the accessors and mutators will do the translation for you.

    public function setCredit_card_numberAttribute($value)
    {
        $this->cc_number = $value;
    }

    public function getCredit_card_numberAttribute()
    {
        return $this->attributes['cc_number'];
    }
Khare's avatar

Couldn't you circumvent this by using HTML and Blade? In your view you would do it like this:

<input type="text" name="first_name" value="{{ $model->property }}">

Though I agree this feels clunky since you have to have a form for both new and edit instead of one partial.

1 like
Spencer's avatar

Snapey, that will actually fix this problem and other issues I've run into. This is perfect.

And here is the documentation if anyone else finds this and needs more info like I did. https://laravel.com/docs/5.2/eloquent-mutators

Khare, that would work, but I really would prefer to keep with the LarvelCollective as much as possible as it is a large part of why I enjoy the Laravel Framework.

Spencer's avatar

@Snapey, could you explain how that works in more detail...

I don't think I quite understand the Docs on it.

And I believe in this video Jefferey Way mentions Accessors and Mutators though he only shows a mutator. https://laracasts.com/series/laravel-5-fundamentals/episodes/11

If I have a form bound to a model "order" and that model has a field called "cell" that I want to use to auto-populate an input with a name "cell_phone" I thought I would create an accessor such as this in the model:

  public function getCellPhoneAttribute()
  {
      return $this->attributes['cell'];
  }

But that seems to do nothing... no errors pop up.... but the task isn't accomplished either. I don't expect errors to show up if I add a field incorrectly, but I just thought I'd mention that since on forums people always ask if any errors showed up.

I also tried this:

  public function getCellPhoneAttribute()
  {
      return $this->cell;
  }

Nothing different it seems...

Snapey's avatar

the problem could the the underscores. I'm not sure how its resolved.

getCellPhoneAttribute should respond to $model->cellPhone

but if you ask instead for cell_phone I'm not sure....

have you tried getCell_phoneAttribute ?

Snapey's avatar
Snapey
Best Answer
Level 122

When you say add attributes to the model and then add accessors, is this what you meant by "add"?

I can't remember saying that? I said add mutators and accessors? (one for getting the data, one for setting the data

$appends and $hidden are for adding extra fields or hiding fields when you do something like $model->toArray. In your case if you wanted to dump the model somewhere you would need to hide 'cell' and append 'cell_phone' so that the dump has the required names

I just tried using an underscore and Laravel figures it out

After creating an accessor;

    protected function getFullNameAttribute()
    {
        return $this->attributes['name'];
    }

This from tinker shows it responds to both formats;

 $user = App\User::find(8)
=> App\User {#691
     id: 8,
     name: "Mark Snape",
     email: "[email protected]",
     created_at: "2016-12-09 22:25:05",
     updated_at: "2017-01-04 21:25:56",
   }
>>> $user->fullName
=> "Mark Snape"
>>> $user->full_name
=> "Mark Snape"
>>>

So, what do you mean by

but the task isn't accomplished either.

1 like
Spencer's avatar

I interpreted:

You can give the model the new names

as

add attributes to the model

Sorry about that.

And when I said

but the task isn't accomplished either.

I hadn't heard of the $append variable before... so the accessor was pointless as the attribute in question was never getting "accessed" because it was never appended so it didn't know it existed.

Now I have:

    protected $appends = ['full_name', 'cell_phone'];

    public function getFullNameAttribute()
    {
        return $this->first_name . ' ' . $this->last_name;
    }

    public function getCellPhoneAttribute()
    {
        return $this->cell;
    }

And it does work in php tinker to dump the model via toArray() or toJSON()... but it still doesn't auto-populate the input value on the form the model is bound to.

davidpiesse's avatar

I would recommend Sofa Eloquence.

Allows you to en-masse define a array of mapping for field names. https://github.com/jarektkaczyk/eloquence

Here is the docs Mappable example https://github.com/jarektkaczyk/eloquence/wiki/Mappable

use Sofa\Eloquence\Eloquence; // base trait
use Sofa\Eloquence\Mappable; // extension trait

class User extends \Eloquent {

    use Eloquence, Mappable;

    protected $maps = [
      // implicit relation mapping:
      'profile' => ['first_name', 'last_name'],

      // explicit relation mapping:
      'picture' => 'profile.picture_path',

      // simple alias
      'dev_friendly_name' => 'badlynamedcolumn',
    ];

    public function profile()
    {
      return $this->belongsTo(Profile::class); // *
    }

1 like
Spencer's avatar

Looks like a nice enough package, but I just got this working... just had to change the way I was getting the data to the view by sending it through 'toArray()' I didn't realize it wasn't already doing that.

Snapey's avatar

The form model binding in Laravel collective should have taken care of it.

If you create form and bind it to e.g. $order then when you create a text input form element and you tell it the field name is cell_phone then the form should name the element cell_phone and try to get data from $order->cell_phone which hits the accessor and pulls 'cell' attribute through.

You should not need to cast it to an array, this was only mentioned because you mentioned $appends

1 like
Spencer's avatar

Maybe the collective should handle I don't know but... I was already passing it a different way so I had to switch it over to get it to work. Just took off the ->toArray() and now it works just fine with $order being passed.

Please or to participate in this conversation.