Nesting Models Relations In Forms - Laravel

13,361

Solution 1

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();
}

Solution 2

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

Share:
13,361

Related videos on Youtube

Goldentoa11
Author by

Goldentoa11

PHP Programmer / Rubyist wannabe.

Updated on August 22, 2022

Comments

  • Goldentoa11
    Goldentoa11 over 1 year

    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() }}
    
  • Goldentoa11
    Goldentoa11 over 10 years
    OK. This makes sense. Next question may be ridiculous, but is there any way to pass the Address into the Person with the other params to save the keystrokes of instantiating and associating the new Address?
  • clod986
    clod986 over 10 years
    I was writing it in the answer, but then I thought: "it's a hasMany() relationship!". You could do it, but you have to find the address you need to output first. Then, pass the second argument to have it autocomplete as such:{{ Form::text("field_x", $person->address->field_x)}}
  • Goldentoa11
    Goldentoa11 over 10 years
    You wouldn't have to 'generate some random key' for a new address, though, right? It'd just be blank, and the code you posted looks like it would handle that just fine.
  • Collin James
    Collin James over 10 years
    Unless you added more than one address. In that event you'd need distinction between those two groups of fields.
  • Goldentoa11
    Goldentoa11 over 10 years
    Hmm. I thought it'd end up like $_FILES.
  • Neeraj
    Neeraj almost 10 years
    @CollinJames: I want to implement same for Event and Admin (in my example) in which one event can be assigned to multiple admin on the same form (Event create form). But i could not understand from your solution that what i need to write in Create method of my Event controller because after writing the code in View of Event "create.blade.php", i get an error "Undefined Variable admins". Can you please provide a full example that provision to save data for associated table from the parent's table Creation form?
  • Marcel Gruber
    Marcel Gruber about 9 years
    This solution worked awesome, but what if you want the user to be able to create or delete address objects?
  • Collin James
    Collin James about 9 years
    Creating works with the example as is. sync() returns an array like so... array('attached' => array(), 'detached' => array(), 'updated' => array()). Just use the 'detached' set of ids to delete the unused addresses.
  • Laerte
    Laerte about 8 years
    Hi, Collin! I'm having problems to fill the form when errors are found and I redirect back to create view. How do you deal with this? Thanks!
  • Sascha Gehlich
    Sascha Gehlich over 5 years
    Finally! Been looking for this for a couple of days. Thanks a bunch!