在Laravel中发布数组错误

时间:2018-01-26 20:43:37

标签: javascript php laravel laravel-5

我有一个模型的编辑表单,一个部分专门用于特定记录的子记录“shipment_details”。

编辑记录将始终显示至少一个现有的shipment_detail记录。目前我的“shipping_details”的HTML就是来自Blade:

<tbody>
    @foreach($shipment_details as $sd)
    <tr style="height:40px">
        <td style="width:8%;text-align:center;">{{Form::text('shipment_details['.$sd->id.'][piecesNumber]', $sd->pieces_number, array('class' => 'form-control','placeholder'=>'No. Pieces','required','id'=>'piecesNumber'))}}
        </td>
        <td style="width:16%;text-align:center;">
            {!! Form::select('shipment_details['.$sd->id.'][piecesType]', $piecetypes, $sd->pieces_type, ['id' => 'pieces_type', 'class' => 'form-control full-width','required']) !!}    
        </td>
        <td>
            {!! Form::select('shipment_details['.$sd->id.'][rateType]', $ratetypes, $sd->rate_type, ['id' => 'rateType', 'class' => 'form-control full-width','required']) !!}
        </td>
        <td style="width:16.5%;text-align:center;">
            {{Form::text('shipment_details['.$sd->id.'][weight]', $sd->weight, array('class' => 'form-control','placeholder'=>'Weight','required','id'=>'weight'))}}    
        </td>
        <td style="width:16.5%;text-align:center;">
            {{Form::select('shipment_details['.$sd->id.'][hazmat]',array(
                                    '0'=>'No',
                                    '1'=>'Yes',
                                ), $sd->hazmat, array('class' => 'form-control','id'=>'hazmat'))}}   
        </td>
        <td style="width:16.5%;text-align:center;">
                            {{Form::text('shipment_details['.$sd->id.'][description]', $sd->description, array('class' => 'form-control','placeholder'=>'Description','required','id'=>'description'))}} 
        </td>
        <td style="width:16.5%;text-align:center;">
            {{Form::text('shipment_details['.$sd->id.'][charge]', $sd->charge, array('class' => 'form-control','placeholder'=>'Charge','required','id'=>'charge'))}} 
        </td>
        <td><button type="button" name="add" id="add" class="btn btn-success">Add More</button></td>
    </tr>

    @endforeach
</tbody>

但是如果需要添加额外的shipment_details,我有一个脚本可以添加下面格式化的其他记录行:

<script>
 $(document).ready(function(){  
      var i=1;  
      $('#add').click(function(){  
            i++;  
           $('#freight_bill_items').append('<tr id="row'+i+'"> <td style="width:8%;text-align:center;">{{Form::text('shipment_details[piecesNumber][]', null, array('class' => 'form-control','placeholder'=>'No. Pieces','required','id'=>'piecesNumber'))}}</td><td style="width:16%;text-align:center;">{!! Form::select('shipment_details[piecesType][]', $piecetypes, 'null', ['id' => 'pieces_type', 'class' => 'form-control full-width','required']) !!} </td><td>{!! Form::select('shipment_details[rateType][]', $ratetypes, null, ['id' => 'rateType', 'class' => 'form-control full-width','required']) !!}</td><td style="width:16.5%;text-align:center;">{{Form::text('shipment_details[weight][]', null, array('class' => 'form-control','placeholder'=>'Weight','required','id'=>'weight'))}}</td><td style="width:16.5%;text-align:center;">{{Form::select('shipment_details[hazmat][]',array('No'=>'No','Yes'=>'Yes',), null, array('class' => 'form-control','id'=>'hazmat'))}}</td><td style="width:16.5%;text-align:center;">{{Form::text('shipment_details[description][]', null, array('class' => 'form-control','placeholder'=>'Description','required','id'=>'description'))}}</td><td style="width:16.5%;text-align:center;">{{Form::text('shipment_details[charge][]', null, array('class' => 'form-control','placeholder'=>'Charge','required','id'=>'charge'))}}</td><td><button type="button" name="remove" id="'+i+'" class="btn btn-danger btn_remove">X</button></td></tr>');   
      });  
      $(document).on('click', '.btn_remove', function(){  
           var button_id = $(this).attr("id");   
           $('#row'+button_id+'').remove();
           $( 'input[name^="shipment_details[charge][]"]' ).trigger( "change" );
      });

 });
</script>

当我发布数据时,我的问题就出现了,现有的数据是“正确排列”的,但是新数据不是,现在给我一个未定义的索引记录。

以下是测试记录的shipment_details的当前POST数据输出:

shipment_details

array:8 [▼
  13149 => array:7 [▼
    "piecesNumber" => "1"
    "piecesType" => "1"
    "rateType" => "1"
    "weight" => "12"
    "hazmat" => "0"
    "description" => "124"
    "charge" => "12.00"
  ]
  "piecesNumber" => array:1 [▼
    0 => "3"
  ]
  "piecesType" => array:1 [▼
    0 => "2"
  ]
  "rateType" => array:1 [▼
    0 => "2"
  ]
  "weight" => array:1 [▼
    0 => "1200"
  ]
  "hazmat" => array:1 [▼
    0 => "Yes"
  ]
  "description" => array:1 [▼
    0 => "desc2"
  ]
  "charge" => array:1 [▼
    0 => "40.00"
  ]
]

正如您所看到的,除了现有记录之外,输入都是独立的,因此我的问题必须源于我的表单。有没有人有任何建议?

更新

使用以上输出:

这是应该如何发送(或以类似的格式):

  13149 => array:7 [▼
    "piecesNumber" => "1"
    "piecesType" => "1"
    "rateType" => "1"
    "weight" => "12"
    "hazmat" => "0"
    "description" => "124"
    "charge" => "12.00"
  ]

由于新记录尚未分配记录ID,我不相信新记录的顶行会相同,但这可以解释我的请求。

更新

控制器的一部分,其中有关于shipment_detail的部分

foreach ($request->shipment_details as $id => $details) {
            $shipdetail = Shipment_Detail::updateOrCreate(['id' => $id], [
            'pieces_type' => $details['piecesType'][0],
            'pieces_number' => $details['piecesNumber'][0],
            'rate_type' => $details['rateType'][0],
            'weight' => $details['weight'][0],
            'charge' => $details['charge'][0],
            'description' => $details['description'][0],
            'hazmat' => $details['hazmat'][0]
                ]);
        }

1 个答案:

答案 0 :(得分:2)

你的问题没有明显而简单的解决方案。

首先,从您当前的html标记中,您可以执行以下操作:

// Regroup post fields to required arrays' structure:

$new_items = [];
foreach ($request->shipment_details['piecesTtype'] as $key => $value) {
    $new_items[] = [
        'pieces_type' => $value,
        'pieces_number' => $request->shipment_details['piecesNumber'][$key],
        'rate_type' => $request->shipment_details['rateType'][$key],
        'weight' => $request->shipment_details['weight'][$key],
        'charge' => $request->shipment_details['charge'][$key],
        'description' => $request->shipment_details['description'][$key],
        'hazmat' => $request->shipment_details['hazmat'][$key],
    ];
}

// so, as these are new items - you can only create them.
// To distinguish existing items from new ones you can:

foreach ($request->shipment_details as $id => $details) {
    if (is_numeric($id)) {  // or any other function that checks if array key is a numeric value like 13149
        // update with $details
    }
}

另一种方法是您可以将html标记重写为:

<!-- I put only excerpt of fields -->
<input type="text" name="shipment_details[13149][piecesNumber]" value="" />

<!-- New fields will be added with an explicit indexing: -->
<input type="text" name="shipment_details[1][piecesNumber]" value="" />
<input type="text" name="shipment_details[2][piecesNumber]" value="" />
<input type="text" name="shipment_details[3][piecesNumber]" value="" />
<!-- and so on -->

在这种情况下,您将获得按需分组的项目,但案例是您将拥有1,2,3及更多索引 这将被视为循环中的ID:

foreach ($request->shipment_details as $id => $details) {

    // as you have id = 1 for example, this record
    // will be updated if it exists, and as a result
    // wrong data will be in a database.
    $shipdetail = Shipment_Detail::updateOrCreate(['id' => $id], [
        ....
    ]);
}

同样在这种情况下,您需要修改js以便计算某处的字段数并在shipment_details[%INDEX%][piecesNumber]中输出正确的索引。

第三解决方案如下。您重建了html布局,添加了带有项目ID的特殊字段。

示例,同样只是部分字段:

<!-- Group 1, an existing record-->
<input type="hidden" name="shipment_details[itemId][]" value="13149" />
<input type="text" name="shipment_details[piecesNumber][]" value="Some existsing value" />
<input type="text" name="shipment_details[weight][]" value="Another existsing value" />

<!-- Group 2, new record-->
<input type="hidden" name="shipment_details[itemId][]" value="0" />
<input type="text" name="shipment_details[piecesNumber][]" value="Value will be input by user" />
<input type="text" name="shipment_details[weight][]" value="Value will be input by user" />

<!-- Group 3, new record-->
<input type="hidden" name="shipment_details[itemId][]" value="0" />
<input type="text" name="shipment_details[piecesNumber][]" value="Value will be input by user-2" />
<input type="text" name="shipment_details[weight][]" value="Value will be input by user-2" />

在这种情况下,您的数组将像现在一样构建,但不会有任何数字索引。 再次迭代它并创建所需的数组:

$new_items = $existsing_items = [];
foreach ($request->shipment_details['itemId'] as $key => $value) {
    if ($value != 0) {
        $existing_items[] = [
            'id' => $value,
            'pieces_number' => $request->shipment_details['piecesNumber'][$key],
            'rate_type' => $request->shipment_details['rateType'][$key],
            // other values
        ];
        // or update immediately
    } else {
        $new_items[] = [
            'pieces_type' => $value,
            'pieces_number' => $request->shipment_details['piecesNumber'][$key],
            'rate_type' => $request->shipment_details['rateType'][$key],
            // other values
        ];
        // or insert immediately
    }
}

但在这种情况下,一些坏人可以修改shipment_details[itemId]的值,而不是0 值将存在实际值,并且您将再次更新数据库中的错误数据。

所以,第一个解决方案仍然是最安全的。当然,有人可以改变 现有ID字段的值,但我想您可以检查此类货件详细信息是当前用户的属性还是任何其他条件。

也许您可以将字段名称拆分为现有字段和新字段,例如:

<!-- Group 1, an existing record-->
<input type="text" name="existsing_details[13149][piecesNumber]" value="Some existsing value" />
<input type="text" name="existsing_details[13149][weight]" value="Another existsing value" />

<!-- Group 2, another existing record-->
<input type="text" name="existsing_details[13150][piecesNumber]" value="Some existsing value" />
<input type="text" name="existsing_details[13150][weight]" value="Another existsing value" />

<!-- Group 3, new record-->
<input type="text" name="new_shipment_details[piecesNumber][]" value="Value will be input by user" />
<input type="text" name="new_shipment_details[weight][]" value="Value will be input by user" />

<!-- Group 4, new record-->
<input type="text" name="new_shipment_details[piecesNumber][]" value="Value will be input by user" />
<input type="text" name="new_shipment_details[weight][]" value="Value will be input by user" />

在这种情况下,您可以迭代existsing_details并更新值,因为它们是现有值。 对于新项目,您使用上面的代码:

// Regroup post fields to required arrays' structure:

$new_items = [];
foreach ($request->new_shipment_details['piecesType'] as $key => $value) {
    $new_items[] = [
        'pieces_type' => $value,
        'pieces_number' => $request->new_shipment_details['piecesNumber'][$key],
        'rate_type' => $request->new_shipment_details['rateType'][$key],
        // other fields
    ];
    // or insert immediately
}

选择哪种方式取决于你。