0

I'm trying to pass multiple arrays via a form to a Laravel Controller and attach form values to a relationship.

I've tried to loop through the Request array but i get an 'undefined index' error and i know i'm not getting to the data somehow. Thanks in advance.

form.php

<form method="POST" action="{{ route('/trs') }}">
  @csrf
<input type="hidden" name="name[]" value="{{ $item->name }}" />
<input type="hidden" name="product_id[]" value="{{ $item->product_id }}" />
<input type="hidden" name="price[]" value="{{ $item->price }}" />
<input type="hidden" name="quantity[]" value="{{ $item->quantity }}" />
<button type="submit" class="btn btn-primary">
 Buy
</button>
 </form

Controller

  public function purchase(Request $request)
  {
         $data = $request->except('_token');
         $user= User::find(Auth::user()->id);
             foreach ($data as $item) {
              $ids = $item['product_id'];
              $names = $item['name'];
              $prices = $item['price'];
              $quantities = $item['quantity'];
              $orders->products()->attach([$ids => ['quantity' => $quantities, 'price' => $prices]]);
           }
  }
4
  • 1
    how is your product_id being submitted through the request? i don't see a hidden input for that in form.php. trying to access $item['product_id'] when product_id hasn't been set might explain why you are getting that error. Commented Oct 22, 2019 at 20:17
  • why are you trying to use arrays, you have one set of values? Commented Oct 22, 2019 at 20:20
  • @lagbox it's not a set, they are dynamic so could have more than one of each. Commented Oct 22, 2019 at 20:26
  • @Erich i've edited the question. The issue isn't with the product_id Commented Oct 22, 2019 at 20:28

2 Answers 2

3

Your foreach is iterating over the inputs, not the arrays in those inputs:

foreach ($data as $item)

In the first iteration $item is the name array. In the second iteration $item is the product_id array, etc. name doesn't have an index named name, price or quantity, its indexes are numerical (0-indexed).

One way would be to iterate those inputs specifically which are arrays:

for ($i = 0; $i < count($data['names']); $i++) {
    $name = $data['name'][$i];
    $product_id = $data['product_id'][$i];
    $price = $data['price'][$i];

    ...
}

There are assumptions being made here but hopefully that illustrates what you need to do if you want to keep using the inputs named the way they are currently.

Updated:

If you wanted to change the names of the inputs you might have an easier time with them being grouped:

<input type="hidden" name="items[{{ $item->id }}][name]" value="{{ $item->name }}" />
<input type="hidden" name="items[{{ $item->id }}][price]" value="{{ $item->price }}" />
...

foreach ($request->input('items', []) as $id => $item) {
    $name = $item['name'];
    $price = $item['price'];
    ...
}

Now the inputs that relate to a single item are grouped into an array together by the item's id.

When you are adding fields dynamically you will have to make sure you are also using this similar naming which includes a key to group them by, in this case the 'id'.

items[27][name]
items[27][price]
...
Sign up to request clarification or add additional context in comments.

2 Comments

thanks, it works. Is there a better way to pass the inputs though?
@LDUBBS similar to Saly 3301's answer, i updated my answer for you
1

If your form is inside a foreach of items collection, set the item ID as the array name and the attributes as keys like so

<form method="POST" action="{{ route('/trs') }}">
    @csrf
    <input type="hidden" name="{{ $item->id }}[product_id]" value="{{ $item->id }}" />
    <input type="hidden" name="{{ $item->id }}[name]" value="{{ $item->name }}" />
    <input type="hidden" name="{{ $item->id }}[price]" value="{{ $item->price }}" />
    <input type="hidden" name="{{ $item->id }}[quantity]" value="{{ $item->quantity }}" />
    <button type="submit" class="btn btn-primary">
        Buy
    </button>
</form

If you do $request->all() you'll see that there are no name or price keys, all keys are just 0 so you have to set them explicitly

<sidenote> Do you really have a route named /trs? shouldn't that be a url('/trs')? </sidenote>

<sidenote> You can get the authenticated user by just auth()->user() </sidenote>

Hope this helps

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.