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

unitedworx's avatar

Any better way to transform this html input array?

i have the below html code which gets duplicated when users click "add" so they can add many offers to an item. (it has a lot more fields but keeping simple here) the returned array i get back is not easy to work with and i prefer it to be structured a bit differently as shown below.

i know i can do something like offers_to_add[0][title] to achieve this but this will be very ugly since i will need to update the array index each time i duplicate it via javascript which i dont think is a good idea.

What i have done is written some code to transform my array in php exactly like I want it but I am not sure if there is a simpler/cleaner way! anyone else came across this hurdle? any cleaner way to do this?

<div class="offer">
    <input type="text" name="offers_to_add[title][]"  >
    <input type="text" name="offers_to_add[text][]"  >
    <input type="text" name="offers_to_add[amount][]"  >
</div>
<!-- add more btn - duplicates the above offer div  -->

returned offers_to_add array has this form

array:3 [
  "title" => array:2 [
    0 => "this is a test 1"
    1 => "this is another test 2"
  ]
  "text" => array:2 [
    0 => "title 1"
    1 => "title 2"
  ]
  "amount" => array:2 [
    0 => ""
    1 => ""
  ]
]

i need it to be

array:2 [
  0 => array:3 [
    "title" => "title 1"
    "text" => "this is a test 1"
    "amount" => ""
  ]
  1 => array:3 [
    "title" => "title 1"
    "text" => "this is a test 1"
    "amount" => ""
  ]
]

this block of code does the job to transform the array. but yet still feels a bit hacky! any cleaner better way of getting the array the way i need it?

       $transformed_data = array();
       $keys = array_keys($offers_to_add);
       foreach ( head($offers_to_add) as $index => $value) {
           foreach ( $keys as $i => $key_name) {
            $transformed_data[$index][$key_name] = array_get($offers_to_add,$key_name.'.'.$index); 
           }
        }
0 likes
5 replies
ohffs's avatar

Would it maybe easier/cleaner to have something like :

<div class="offer">
    <input type="text" name="offer_titles[]"  >
    <input type="text" name="offer_texts[]"  >
    <input type="text" name="offer_amounts[]"  >
</div>

The you can loop over it like :

foreach($offer_titles as $index => $title) {
  $transformed_data[] = array(
    'title' => $title,
    'text' => $offer_texts[$index],
    'amount' => $offer_amounts[$index]
  );
}
1 like
Snapey's avatar

you don't have to provide the index, you can use the empty array type syntax. put your empty field before the element name

offers[][title]

you should then be able to foreach the offers

unitedworx's avatar

@Snapey if you dont provide the index then each of the attributes in an offer will have a different index! so this definitely does not work!

@ohffs i tried that approach but its less helpful from what i am trying to do. With the array structure i want to achieve i can easily do the following in php :) which is much much much cleaner! You can't do this with a different array structure!

        foreach ( $offfer_to_add as $index => $data) {
                Offer::create($data);
        }

The best way i came up so far is to following this approach in html and increment the index via jQuery when i clone the element

<div class="offer">
    <input type="text" name="offers_to_add[1][title]"  >
    <input type="text" name="offers_to_add[1][text]"  >
    <input type="text" name="offers_to_add[1][amount]"  >
</div>
<!-- add more btn - duplicates the above offer div -->
<button type="button" class="btn btn-default center-block"
        data-action="clone-element" data-element=". offer" >
    Add more offers <i class="fa fa-plus"></i>
</button>
    $(document).on('click', '[data-action="clone-element"]', function() {
        var element = $(this).data('element');
        var html = $(element).last().clone();
        //increment input array index ( e.g [1] to [2] ) to have clean arrays in php to work with
        html.find('[name]').each(function(){
            this.name = this.name.replace(/\[(\d+)\]/,function(str,p1){return '[' + (parseInt(p1,10)+1) + ']'});
            this.id = this.id.replace(/\[(\d+)\]/,function(str,p1){return '[' + (parseInt(p1,10)+1) + ']'});
        });
        $(element).last().after(html);
    });

if you guys found a better solution i am all ears! at the moment incrementing the index via jQuery seems the cleanest way!

1 like
PLB-RR's avatar

I would do it like this:

<div class="offer">
    <input type="text" name="titles[][title]"  >
    <input type="text" name="texts[][text]"  >
    <input type="text" name="amounts[][amount]"  >
</div>

$offers = array_replace_recursive($titles, $texts, $amounts);

And if you don't need to mutate any data you can insert them directly to your table with

Offer::insert($offers);
1 like

Please or to participate in this conversation.