Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nesting Models Relations In Forms - Laravel

In laravel, is there some way of nesting related resources in a form?

Say I have this:

class Person extends Eloquent {
  public function addresses() {
    return $this->hasMany("Address");
  }
}

class Address extends Eloquent {
  public function person() {
    return $this->belongsTo("Person");
  }
}

and I want a Person form to collect information about that Person's Addresses. Does laravel facilitate this in a way that is equivalent to Rails' accepts_nested_attributes_for :address and fields_for :address?

I'd just like something simple where I can include the Address fields with the results of the Person form, since the Address doesn't really exist apart from the Person. Does this make sense?

== EDIT ==

This is hypothetical code

What I'm looking for is something that would resemble this:

{{ Form::model(new Person, array("action" => "admin\PersonController@store", "method" => "POST")) }}

{{ Form::text("name", array(...)) // <input name='person[name]' ... /> }}


{{ Form::email("email", array(...)) // <input name='person[email]' ... /> }}

{{ Form::fields_for("addresses"/* Would be name of relation */) }}

  {{ Form::text("street_address") // <input name='person[addresses][][street_address]' ... /> }}

{{ Form::close_fields() }}

{{ Form::close() }}
like image 564
Goldentoa11 Avatar asked Dec 19 '13 15:12

Goldentoa11


2 Answers

You are on the right track with the input names.

Form

// Form open, Person fields, etc...

<h2>Addresses</h2>
@foreach ($addresses as $address)

    <fieldset>

        {{ Input::text('addresses['.$address->id.'][address_1]', $address->address_1) }}
        {{ Input::text('addresses['.$address->id.'][address_1]', $address->address_2) }}
        {{ Input::text('addresses['.$address->id.'][city]', $address->city) }}
        {{ Input::text('addresses['.$address->id.'][state]', $address->state) }}
        {{ Input::text('addresses['.$address->id.'][zip]', $address->zip) }}

    </fieldset>

@endforeach

// Form Close

If you want to add addresses you'll need to generate some random key to use instead of the address id. This will keep the fields grouped.

Controller Logic

This is how I would handle input, using 'fillable' to filter the data going into the models.

// Get the Person model, fill, save, etc...

$addressIds = array();
foreach (Input::get('addresses', array()) as $id => $addressData)
{
    $address = Address::find($id) ?: new Address;
    $address->fill($addressData);
    $address->save();
    $addressIds[] = $address->id;
}

$changes = $person->addresses()->sync($addressIds);

// Delete the unused addresses
foreach ($changes['detached'] as $detachedAddressId)
{
    $address = Address::find($detachedAddressId);
    if (!empty($address)) $address->delete();
}
like image 92
Collin James Avatar answered Oct 16 '22 23:10

Collin James


Now you can use the package "modelform" to create a form for various models or even a set of forms for relations.

https://github.com/andersondanilo/modelform

like image 40
Anderson Danilo Avatar answered Oct 16 '22 22:10

Anderson Danilo