Ad

Laravel Uniqueness Of Combination Validation Rule

I am trying to make a validation rule on a unique combination of two attributes. An Etudiant may choose only once one Theme. I've made a table etudiantsChoixThemes which records the different choices. Here is the etudiantsChoixThemes's table structure :

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateEtudiantsChoixThemesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('etudiantsChoixThemes', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->integer('idEtudiant');
            $table->integer('idThematique');
            $table->string('description');
            $table->string('outils');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('etudiantsChoixThemes');
    }
}

The studentChooseTheme blade view where i get the choice made by the currently logged in etudiant

@extends('layouts.layout')
@section('content')
<body>
{{$theme->intitule}} {{$theme->categorie}}
<div class="container_fluid">
<div class="row">
<div class="alert alert-danger print-error-msg" style="display: none;">
<ul></ul>
</div>
<div class="alert alert-success print-success-msg" style="display: none;">
<center></center>
</div>
</div>
</div>
<form method="post" action=" {{route('registerThemeChoice', $theme->id)}} ">
    @csrf
    <fieldset>Comment comprenez-vous la thématique proposée</fieldset>
    <input type="hidden" name="idEtudiant" value=" {{Auth::guard('web')->user()->id}} ">
    <input type="hidden" name="idThematique" value=" {{$theme->id}} ">
    <textarea name="description" required> {{old('description')}} </textarea>
    <fieldset>Quels outils comptez-vous utiliser pour mener à bien le projet?</fieldset>
    <textarea name="outils" required> {{old('outils')}} </textarea>
    <input class="button-info" type="submit" name="submit" id="submit" value="Valider">
</form>
    <a  target="_blank" rel="nofollow noreferrer" href=" {{url('themes/' .$theme->id)}} "><button class="button-danger">Annuler</button></a>
</body>
@jquery
<script type="text/javascript">
    $(function(){

        $('#submit').on('click', function(e){
            e.preventDefault();
            var _token = $("input[name='_token']").val();
            var idEtudiant = $('input[name=idEtudiant]').val();
            var idThematique = $('input[name=idThematique]').val();
            var description = $('textarea[name=description]').val();
            var outils = $('textarea[name=outils]').val();

                $.ajax({
                    url: "{{route('registerThemeChoice',$theme->id)}}",
                    type: 'POST',
                    data: {
                        _token:_token,
                        idEtudiant:idEtudiant,
                        idThematique:idThematique,
                        description:description,
                        outils:outils
                    },
                    success: function(data){
                        if($.isEmptyObject(data.error)){
                            // alert(data.success);
                            $('.print-error-msg').css('display','none');
                            toastr.success(" Votre choix est enregistré ");
                        }
                        else{
                            // console.log(data.error);
                            printErrorMsg(data.error);
                        }
                    }
                });


        function printErrorMsg (msg) {

            $(".print-error-msg").find("ul").html('');

            $(".print-error-msg").css('display','block');

            $.each( msg, function( key, value ) {

                $(".print-error-msg").find("ul").append('<li>'+value+'</li>');

            });

        }
        });
    });
</script>
@endsection

Here is the studentChooseThemeController

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Theme;
use App\EtudiantsChoixTheme;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;

class studentChooseThemeController extends Controller
{
    public function index($id){
        $theme = Theme::findOrFail($id);
        return view('studentChooseTheme', ['theme' => $theme]);
    }

    public function etudiantChoixTheme(Request $request, $id){
        // $theme = Theme::findOrFail($id);
        $validator = Validator::make($request->all(),[
            'description' => 'required',
            'outils' => 'required',
            'idThematique' => Rule::unique('etudiantsChoixThemes')->where(function ($query) use($idEtudiant, $idThematique) {
                return $query->where('idEtudiant', $idEtudiant)
                ->where('idThematique', $idThematique);
            }),
        ]);

        if ($validator->fails()) {

        return response()->json(['error'=>$validator->errors()->all()]);

        }
        $etudiantChoixTheme = new EtudiantsChoixTheme;
        $etudiantChoixTheme->idEtudiant = $request->input('idEtudiant');
        $etudiantChoixTheme->idThematique = $request->input('idThematique');
        $etudiantChoixTheme->description = $request->input('description');
        $etudiantChoixTheme->outils = $request->input('outils');
        $etudiantChoixTheme->save();
    }
}

I'm submitting it with ajax and it works fine for what's about the ajax part.. My issue here is with the validation. As I mean it above, I want a unique rule on idEtudiant and idThematique combined: an Etudiant may choose only once a Theme, so there will be in the database an unique combination of idEtudiant with idThematique.

I found something here and applied it as you may have seen in the Controller's code for the idThematique. Yet I'm not getting the result expected.

I've tried this also :

$validator = Validator::make($request->all(),[
            'description' => 'required',
            'outils' => 'required',
            'idThematique' =>'unique:etudiantsChoixThemes,idThematique,'.$this->id.',NULL,id,idEtudiant'. $request->input('idEtudiant'),
        ]);

and this :

        $validator = Validator::make($request->all(),[
            'description' => 'required',
            'outils' => 'required',
            'idThematique' =>'unique:etudiantsChoixThemes,idThematique,NULL,id,idEtudiant'. $request->input('idEtudiant'),
        ]);

The unique combination can still be recorded more than once. Plus I've noticed that with that two last blocks of code above, validation isn't working anymore (for the required parts). Am I missing something here..? Your help would be very welcome. I'm using laravel 5.8

Ad

Answer

You're almost there.

The variables $idEtudiant and $idThematique passing through to the where() function are not set.

This should work:

'idThematique' => Rule::unique('etudiantsChoixThemes')->where(function ($query) {
                return $query->where('idEtudiant', request('idEtudiant'))
                    ->where('idThematique', request('idThematique'));
            })
Ad
source: stackoverflow.com
Ad