Back

Form/Model binding not working


I'm in the process of getting to grips with L4 and I'm having issues with saving/retrieving/updating data with a form/mdel binding.

These are the various issues that I get:

  1. When saving/creating a new contact - a row is added to the contacts table but all values are empty apart from the id and any default values defined in the table definition. If I dd() the inputs they are all set.

  2. When editing an entry /contacts/1/edit I get the following error: Illuminate \ Database \ Eloquent \ ModelNotFoundException which being thrown in line 598 fromvendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php which the error exception for the findOrFail method.

All the field names on the forms match their table column names. What am I missing in getting these parts to play nicely together?

Hopefully all the relevant code is below, thanks for any help.

In my routes.php

Route::model('contacts', 'Contact');
Route::resource('contacts', 'ContactsController');

in my ContactsController.php (just the relevant methods extracted)

	public function store()
	{
		$inputs = Input::all();
		
		$contact = new Contact;

		if ( $contact->save($inputs) )
		{
			return Redirect::route('contacts.index')->with('success', 'New contact added');
		} 
		else 
		{
			return Redirect::back()->with('fail', 'An error occurred saving the contact. Please check the logs')->withInput();
		}
	}

	public function edit($id)
	{
		$contact = Contact::findOrFail($id);

		return View::make('contacts.edit')->withContact($contact);
	}


	public function update($id)
	{
		$this->form->validate($inputs);

		$contact = Contact::findOrFail($id);

		if ( $contact->update($inputs))
		{
			return Redirect::route('contacts.index')->with('success', 'Contact updated');
		} 
		else 
		{
			return Redirect::back()->with('fail', 'An error occurred saving the contact. Please check the logs')->withInput();
		}


	}

in my models/Contact.php

class Contact extends \Eloquent {
	protected $fillable = [];

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

in my contacts/create.blade.php

{{ Form::model(new Contact, [
          'route' => 'contacts.store',
          'class' => 'well'
        ]) 
}}

in my contacts/edit.blade.php

{{ Form::model( $contact, [
         'method'=> 'PATCH',
         'route' => ['contacts.update', $contact->id]
         'class' => 'well'
         ]) 
}}
codeATbusiness replied 5 years ago

Hi BlackPig,

I think you need to specify the fillable fields to your Model as follow:

protected $fillable = array('first_name', 'last_name'); //and another fields you need to fill with your Form inputs.

Hope it helps you.

Blackpig replied 5 years ago

Hi thanks, for the reply but that's not the issue - I have populated the $fillable array but it still doesn't save anything.

If I explicitly set the values:


$contact = new Contact;
$contact->first_name = Input::get( 'first_name' );

$contact->save();

the values are saved ok but if I pass the inputs then they don't:

$contact = new Contact;
$contact->save(Input::all());

as I understand it, Laravel/Eloquent should handle that ok.

Blackpig replied 5 years ago

I've learned and discovered a couple of things whilst trying to work out why my form data isn't being saved. I'll leave comments here that may help anyone else that has similar issues.

First up, my form data wasn't being saved with:

$contact = new Contact;
$contact->save(Input::all());

What I needed to do is:

$contact = new Contact;
$contact->fill(Input::all()->save());

I've seen various tuts/examples that use the first example without the ->fill() but I've not been able to get this to work.

The other thing that I've learned is model binding in the routes.php affects what is passed into the controller

In my routes.php I had:

Route::model('contacts', 'Contact');
Route::resource('contacts', 'ContactsController');

this would give me a a uri of contacts/4/edit to edit that contact record.

in my ContactsConroller


public function edit ( $id )
{

}

The $id parameter that is passed is NOT the $id of the contact but the actual Contact Object, so I could have:

public function edit ( Contact $contact )
{
    return View::make('contacts.edit, compact('contact'));
}

If I don't have the Route::model binding set up in the routes.php then the $id parameter is the id value from the url

public function edit ( $id )
{
    $contact = Contact::findOrFail($id);
    return View::make('contacts.edit, compact('contact'));
}
cheanj replied 4 years ago

removed the 'class' => 'well' from the form


Sign in to participate in this thread!



We'd like to thank these amazing companies for supporting us