Bonjour,

Voila je rencontre un petit problème avec mon code.

Ce que je fais

Ma route :

Route::post('/insert',array('as'=>'insert','uses'=>'CriterespersoController@insert'));

Mon controller

   public function insert(Request $request)
   {
     $user = Auth::user();
     foreach ($request->apports as $key => $v)
     {
       $data = array('user_id'=>$user,
                    'name'=>$v,
                    'min'=>$request->min [$key],
                    'max'=>$request->max [$key]);
      $criteresperso = $user->criterespersos()->insert($data);
     }
     return redirect()->route('bilans.index');
   }

J'ai aussi essayé ça pour le controller (mais le résultat est le même) :

public function insert(Request $request)
   {
     $user = Auth::user();
     foreach ($request->apports as $key => $v)
     {
       $data []  = [ 
            'user_id'=>$user,
            'name'=>$v,
            'min'=>$request->min [$key],
            'max'=>$request->max [$key] 
       ];
     }
       $criteresperso = $user->criterespersos()->insert($data);

     return redirect()->route('bilans.index');

Mes models :

public function user()
    {
       return $this->belongsTo(User::class);
    }

      public function criterespersos()
    {
       return $this->hasMany(Criteresperso::class);
    }

Ma vue :

    {!! Form::open(array('route'=>'insert', 'id'=>'frmsave', 'method'=>'post')) !!}
    {{ csrf_field() }}

Ce que je veux

Je souhaite enregistrer plusieurs lignes d'un coup dans une table de ma bdd

Ce que j'obtiens

Seule une ligne est insérée dans ma table (alors que j'en ai remplie 2 ou 3 dans mon formulaire), et le user_id est à "0" dans la table.
Si je remplace insert($data) par create($data) dans mon controller le user_id est cette fois-ci bien renseigné dans ma table mais ça ne m'enregistre toujours que la première des lignes saisies.

8 réponses


personne ?

Deja tu passe tout le $user alors qu'il faudrait ne passer que $user->id:
'user_id' => $user->id

Ensuite un dd($request->all()) serait judicieux pour savoir si tu recupere bien plusieurs enregistrements.

C'est un classique il faut nommer le name des inputs / select de ton form avec la notation tableau: avec [] à la fin.

Bonjour force-rouge et merci pour ta réponse,
Pour le 'user_id' => $user->id c'est bon, le problème est réglé, je récupère bien mon user_id maintenant.
Quand je fais un dd($request->all()), je n'ai effectivement qu'une seule entrée... Pourtant j'ai bien nommé les "name" des input/select avec [] à la fin. Voici la partie concernée de mon form :

@extends('layouts.app')
@section('content')
@include('aide')

<div class="container">
  <div class="row col-md-offset-2 col-md-10">
  <table class="table table-striped" id="nutrition">
    {!! Form::open(array('route'=>'insert', 'id'=>'frmsave', 'method'=>'post')) !!}
    {{ csrf_field() }}

    <thead>
      <tr>
        <th>Critère</th>
        <th>minimum</th>
        <th>maximum</th>
        <th style="text-align:center"><a href="#" class="btn btn-primary addRow"><i class="fa fa-plus" aria-hidden="true"></i></a></th>
        <th><button type="submit" class="btn btn-md btn-primary pull-right">Enregistrer</button></th>
      </tr>
    </thead>
    <tbody class="text-primary">
      <tr><td><select class="form-control" id="apports" name="apports[]">
        <option value="0" selected="true" readonly="true">Choisir</option>
        <option value="energie_kJ">Energie kJ</option>
        <option value="energie_kcal">Energie kcal</option>
        <option value="proteines">Proteines</option>
        <option value="indice_glycemique">Indice glycemique</option>
       </select></td>
        <td><input type="text" name="min[]" class="form-control min" size="7"/></td>
        <td><input type="text" name="max[]" class="form-control max" size="7"/></td>
        <td style="text-align:center"><a href="#" class="btn btn-danger remove"><i class="fa fa-trash" aria-hidden="true"></i></a></td>
        <td></td>
      </tr>
      </tbody>
      {!! Form::close() !!}
    </table>
  </div>
</div>

@stop

Bon j'ai testé avec ton code html et chez moi ça marche !

@extends('layouts.app')
<div class="container">

<form action="" method="POST">
    <input type="hidden" name="_token" value="{{ csrf_token() }}">
    <table class="table table-striped">
    @for($i=0; $i<5; $i++)
        <tr>
            <td>
                <select class="form-control" id="apports" name="apports[]">
                    <option value="0" selected="true" readonly="true">Choisir</option>
                    <option value="energie_kJ">Energie kJ</option>
                    <option value="energie_kcal">Energie kcal</option>
                    <option value="proteines">Proteines</option>
                    <option value="indice_glycemique">Indice glycemique</option>
                </select>
            </td>
            <td>
                <input type="text" name="min[]" class="form-control min" placeholder="min" size="7"/>
            </td>
            <td>
                <input type="text" name="max[]" class="form-control max" placeholder="max" size="7"/>
            </td>
            <td style="text-align:center">
                <a href="#" class="btn btn-danger remove"><i class="fa fa-trash" aria-hidden="true"></i></a>
            </td>
          </tr>
    @endfor
    </table>

    <div class="card">
        <div class="card-block">
            <button type="submit" class="btn btn-primary">SUBMIT</button>
        </div>
    </div>
</form>
</div>

Bien sûr j'ai rajouté une boucle for car dans ton code il n'y a qu'une ligne et voici le dd de request::all() avec des tests bidons:

array:4 [▼
  "_token" => "oqktbKYTqEVJ3wfyz8jR3FZZvKVyaYl3bgFZhUEq"
  "apports" => array:5 [▼
    0 => "proteines"
    1 => "indicrajouté e_glycemique"
    2 => "0"
    3 => "energie_kJ"
    4 => "proteines"
  ]
  "min" => array:5 [▼
    0 => "4"
    1 => "5"
    2 => "3"
    3 => "1"
    4 => ""
  ]
  "max" => array:5 [▼
    0 => "5"
    1 => "8"
    2 => "2"
    3 => ""
    4 => "4"
  ]
]

En fait, à la place de la boucle for que tu utilises, j'ai un script qui fonctionne pour me rajouter des lignes dans le form mais qui apparemment ne sauvegarde pas les lignes rajoutées. Il me manque peut-être quelque chose dans ce code alors ?

<script type="text/javascript">
$('.addRow').on('click', function(){
  addRow();
});
function addRow()
{
  var tr ='<tr>'+
  '<td>'+'<select class="form-control apports" id="apports" name="apports[]">'+
    '<option value="0" selected="true" disabled="true">Choisir</option>'+
    '<option value="energie_kJ">Energie kJ</option>'+
    '<option value="energie_kcal">Energie kcal</option>'+
    '<option value="proteines">Proteines</option>'+
    '<option value="indice_glycemique">Indice glycemique</option>'+
  '</select>'+'</td>'+
    '<td><input type="text" name="min[]" class="form-control min" size="7"/></td>'+
    '<td><input type="text" name="max[]" class="form-control max" size="7"/></td>'+
    '<td><a href="#" class="btn btn-danger remove"><i class="fa fa-trash" aria-hidden="true"></i></a></td>'+
  '</tr>';
  $('tbody').append(tr);
};
$('body').on('click','.remove', function(){
  var l=$('tbody tr').length;
  if(l==1)
  {
  alert('Vous ne pouvez pas supprimer la dernière ligne')
  }
  else{
  $(this).parent().parent().remove();
  }
});
</script>

je reviens sur ton pb un peu tard mais je voudrais de quelle manière se fait la soumission de ton formulaire:
par ajax ou une simple redirection sur la même page ? Ou peut être fais tu une validation via JS avant soumission qui échoue ?
La soumission en 'POST' devrait contenir toutes tes rows,
cependant si tu utilise jquery ou autre pour soumettre le form en ajax, il est possible que les rows créées dynamiquement ne soient pas associées au données du formulaire.
Enfin vu que tu utilise jquery tu peux connaitre le contenu de ta requête avant la soumission via un code du genre:

$( document ).ready(function() {
    $('#form').on('submit', function(e){
        e.preventDefault();

        console.log($(this).serializeArray()); // tu devrais récupérer une liste d'objets, dont les champs dynamiquement créés

        //return false;  // false pour empêcher la soumission, sinon il faut return true
    });
});

Tu sauras alors si toutes tes row sont bien postées.

Je viens de tester ton code JS et cela fonctionne chez moi ( le .addRow et le remove )
par compte j'ai wrappé le code dans $( document ).ready(function() { .... }) pour être sûr que ton le DOM est bien chargé

Bonjour force-rouge, merci bien de t'interesser à mon problème.
Pour répondre à ta question, la soumission du formulaire se fait par une simple redirection sur la même page pour le moment.
Je pense en effet que la soumission en 'POST' ne contient pas toutes mes rows.
Par contre je ne sais pas où mettre le code que tu as écris, je le met au début de ma vue ou avant le début du addRow ou après ? J'ai tout essayé et ça ne change rien j'ai toujours 1 seule ligne qui s'enregistre.
Que veut dire "j'ai wrappé le code" ?