Save inputs with PHP/Laravel arrays

Asked

Viewed 3,056 times

2

I have a dynamically generated table where I insert several products. I’m trying to use a for to save these products, but if I only have one product doesn’t work anymore, you need to have more than one. I tried with foreach but it didn’t work.

View:

@extends('layouts.app')

@section('content')
<div class="container">
<div class="row">
    <div class="col-md-12">
        <form method="post" action="{{ route('storeProduct') }}">
            {{ csrf_field() }}
            <div class="panel panel-default">
                <div class="panel-heading">Dashboard</div>
                <div class="panel-body">
                    <table class="table m-0" id="products-table">
                        <thead>
                            <tr>
                                <th>Produto/Serviço</th>
                                <th>Quantidade</th>
                                <th>Valor Unitário</th>
                                <th>Valor Total</th>
                                <th>Remover</th>
                            </tr>
                        </thead>
                        <tbody class="row">

                        </tbody>
                        <tfoot>
                            <tr>
                                <td colspan="5" style="text-align: left;">
                                    <button class="btn btn-info waves-effect w-md waves-light m-b-5" onclick="AddTableRow()" type="button">Adicionar Produto</button>
                                </td>
                            </tr>
                        </tfoot>
                    </table>    
                    <button class="btn btn-primary" type="submit">Incluir Orçamento</button>
                </div>
            </div>
        </form>
    </div>
</div>
</div>
@endsection

@push('js')
<script>

RemoveTableRow = function(handler) {
    var tr = $(handler).closest('tr');
    tr.fadeOut(400, function() {
        tr.remove();
    });
    return false;
};

AddTableRow = function() {

    var newRow = $("<tr>");
    var cols = "";

    cols += '<td class="col-md-4"><input type="text" class="form-control product" name="name[]"></td>';
    cols += '<td class="col-md-2"><input type="text" class="form-control amount" name="amount[]"></td>';
    cols += '<td class="col-md-2"><input type="text" class="form-control price" name="unit_price[]"></td>';
    cols += '<td class="col-md-2 total"><input readonly type="text" class="form-control" name="total_price[]"></td>';
    cols += '<td class="col-md-2">';
    cols += '<button class="btn btn-danger waves-effect w-md waves-light m-b-5" onclick="RemoveTableRow(this)" type="button">Remover</button>';
    cols += '</td>';

    newRow.append(cols);
    $("#products-table").append(newRow);

    $(".amount, .price").unbind('blur keyup');
    $(".amount, .price").on("blur keyup",function(){
        const tr = $(this).parent().parent();

        const quant = parseInt(tr.find('.amount').val());
        const valor = parseInt(tr.find('.price').val());
        var total = quant * valor;

        if (!isNaN(quant) && !isNaN(valor)){
            tr.find('.total').html('<input readonly type="text" class="form-control" name="total_price[]" value=" '+total+' ">');
        }
    });

    return false;
};

</script>
@endpush

$request:

array:5 [▼
   "_token" => "wLRaFmgHxEMtOzPMzzylPFjtJLawgr262kOz4xGf"
   "name" => array:2 [▼
    0 => "Produto 1"
    1 => "Produto 1"
   ]
  "amount" => array:2 [▼
    0 => "2"
    1 => "3"
  ]
  "unit_price" => array:2 [▼
    0 => "200"
    1 => "300"
   ]
   "total_price" => array:2 [▼
   0 => "400"
   1 => "900"
   ]
]

Controller:

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Product;

class ProductsController extends Controller
{

private $product;

public function __construct(Product $product)
{
    $this->product = $product;
}

public function store(Request $request)
{
    for ($i = 0; $i < count($request->all()); $i++) { 
        $this->product = new Product();
        $this->product->name = $request->name[$i];
        $this->product->amount = $request->amount[$i];
        $this->product->unit_price = $request->unit_price[$i];
        $this->product->total_price = $request->total_price[$i];
        $this->product->save();
    }        
}

}
  • In the controller use for ($i = 0; $i < count($request->name); $i++)

  • Yes, I ended up putting it that way. But is this the best way to do it? I wouldn’t have any way of doing it without knowing the name of the camp?

  • The best is not to use <input name="total_price[]">, but yes <input name="product[1][total_price]"> where this Indice 1 is inserted dynamically by javascript. When in the loop use foreach() instead of for()

1 answer

2


There really is a simple way is by using the method create passing the array to store the data, and remembering that its Product class must be configured its fillable as follows:

use Illuminate\Database\Eloquent\Model;

class Product extends Model 
{
    protected $fillable = ['name','amount','unit_price','total_price'];
}

and in the method:

public function store(Request $request)
{
    for ($i = 0; $i < count($request->name); $i++) 
    { 
         $this->product->create([
                    'name' => $request->name[$i],
                    'amount' => $request->amount[$i] ,
                    'unit_price' => $request->amount[$i],
                    'total_price' => $request->total_price[$i]
         ]);
    } 
}

Observing: in his method store had a line: $this->product = new Product(); this cannot happen, because, if you are recreating an instance that has already been set by builder. If by chance you want it that way use, then so: $product = new Product(); and proceed with those commands.

References

Browser other questions tagged

You are not signed in. Login or sign up in order to post.