Problems in validating unique values

1

You see, I have a table Game with the following parameters:

Schema::create('juegos', function (Blueprint $table){
    $table->increments('id');
    $table->integer('numero')->unique();
    $table->string('nombre');
    $table->unsignedInteger('agrupacion_id');
    $table->foreign('agrupacion_id')->references('id')->on('agrupacions');
    $table->text('materiales');
    $table->text('organizacion');
    $table->text('desarrollo');
    $table->string('foto');
    $table->text('observaciones');
    $table->text('variantes');
    $table->timestamps();
});

I want to create a form to modify the values of the table, for which I have this:

@extends('layouts.app')
@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">Modifique los datos del juego</div>

                <div class="card-body">
                    <form method="POST" action="{{$j->id}}" enctype="multipart/form-data">
                        @csrf

                        <div class="form-group row">
                            <label for="numero" class="col-md-4 col-form-label text-md-right">Código del juego</label>

                            <div class="col-md-6">
                                <input id="numero" type="number" class="form-control{{ $errors->has('numero') ? ' is-invalid' : '' }}" name="numero" value="{{ $j->numero }}" required autofocus>

                                @if ($errors->has('numero'))
                                    <span class="invalid-feedback">
                                        <strong>{{ $errors->first('numero') }}</strong>
                                    </span>
                                @endif
                            </div>
                        </div>

                        <div class="form-group row">
                            <label for="nombre" class="col-md-4 col-form-label text-md-right">Nombre del juego</label>

                            <div class="col-md-6">
                                <input id="nombre" type="text" class="form-control{{ $errors->has('nombre') ? ' is-invalid' : '' }}" name="nombre" value="{{ $j->nombre }}" required autofocus>

                                @if ($errors->has('nombre'))
                                    <span class="invalid-feedback">
                                        <strong>{{ $errors->first('nombre') }}</strong>
                                    </span>
                                @endif
                            </div>
                        </div>

                        <div class="form-group row">
                            <label for="agrupacion" class="col-md-4 col-form-label text-md-right">¿Como se organizaran los equipos?</label>

                            <div class="col-md-6">
                                <select id="agrupacion" type="text" class="form-control{{ $errors->has('agrupacion') ? ' is-invalid' : '' }}" name="agrupacion" required autofocus>
                                    @foreach($agrupaciones as $agrupar)
                                        <option value="{{$agrupar->id}}" {{($j->agrupacion_id == $agrupar->id) ? 'selected' : ''}}>{{$agrupar->nombre}}</option>
                                    @endforeach
                                </select>

                                @if ($errors->has('agrupacion'))
                                    <span class="invalid-feedback">
                                        <strong>{{ $errors->first('agrupacion') }}</strong>
                                    </span>
                                @endif
                            </div>
                        </div>

                        <div class="form-group row">
                            <label for="materiales" class="col-md-4 col-form-label text-md-right">Materiales que se utilizaran en el juego</label>

                            <div class="col-md-6">
                                <textarea id="materiales" name="materiales">{{ $j->materiales }}</textarea>

                                @if ($errors->has('materiales'))
                                    <span class="invalid-feedback">
                                        <strong>{{ $errors->first('materiales') }}</strong>
                                    </span>
                                @endif
                            </div>
                        </div>

                        <div class="form-group row">
                            <label for="organizacion" class="col-md-4 col-form-label text-md-right">Como se organizara el juego</label>

                            <div class="col-md-6">
                                <textarea id="organizacion" name="organizacion">{{ $j->organizacion }}</textarea>

                                @if ($errors->has('organizacion'))
                                    <span class="invalid-feedback">
                                        <strong>{{ $errors->first('organizacion') }}</strong>
                                    </span>
                                @endif
                            </div>
                        </div>

                        <div class="form-group row">
                            <label for="desarrollo" class="col-md-4 col-form-label text-md-right">Desarrollo del juego</label>

                            <div class="col-md-6">
                                <textarea id="desarrollo" name="desarrollo">{{ $j->desarrollo }}</textarea>

                                @if ($errors->has('desarrollo'))
                                    <span class="invalid-feedback">
                                        <strong>{{ $errors->first('desarrollo') }}</strong>
                                    </span>
                                @endif
                            </div>
                        </div>

                        <div class="form-group row">
                            <label for="observaciones" class="col-md-4 col-form-label text-md-right">Reglas y observaciones</label>

                            <div class="col-md-6">
                                <textarea id="observaciones" name="observaciones">{{ $j->observaciones }}</textarea>

                                @if ($errors->has('observaciones'))
                                    <span class="invalid-feedback">
                                        <strong>{{ $errors->first('observaciones') }}</strong>
                                    </span>
                                @endif
                            </div>
                        </div>

                        <div class="form-group row">
                            <label for="Variantes" class="col-md-4 col-form-label text-md-right">Variantes</label>

                            <div class="col-md-6">
                                <textarea id="variantes" name="variantes">{{ $j->variantes }}</textarea>

                                @if ($errors->has('variantes'))
                                    <span class="invalid-feedback">
                                        <strong>{{ $errors->first('variantes') }}</strong>
                                    </span>
                                @endif
                            </div>
                        </div>

                        <hr>

                        <div style="margin-left: 35%;">
                            <b><i><u>Habilidades requeridas:</u></i></b><br><br>
                            @foreach($contenidos as $contenido)
                                <input type="checkbox" name="capacidad[]" value="{{$contenido->id}}" @if (old('capacidad[$contenido->id]') == "1") checked @endif> {{$contenido->nombre}}<br>
                            @endforeach
                        </div>

                        <hr>

                        <div class="form-group row">
                            <label for="foto" class="col-md-4 col-form-label text-md-right">Nueva imagen (si es que la quiere modificar)</label>

                            <div class="col-md-7">
                                <input id="foto" type="file" class="form-control{{ $errors->has('foto') ? ' is-invalid' : '' }}" name="foto" />

                                @if ($errors->has('foto'))
                                    <span class="invalid-feedback">
                                        <strong>{{ $errors->first('foto') }}</strong>
                                    </span>
                                @endif
                            </div>
                        </div>

                        <div class="form-group row mb-0">
                            <div class="col-md-6 offset-md-4">
                                <button type="submit" class="btn btn-primary">
                                    Modificar Juego
                                </button>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
@endsection

And this goes through the following validator:

public function rules(){
    return[
        'numero'=>'required|integer|min:0|unique:juegos',
        'nombre'=>'required',
        'materiales'=>'required',
        'organizacion'=>'required',
        'desarrollo'=>'required',
        'observaciones'=>'required'
    ];
}

And in the parameter numero is where my problem comes from, in the validator I have asked that if the game number is detected in the error BBDD, but that means that if I modify a game but I do not change its original number , I will give error. I would have to make that in case of coincidence I checked if its number coincides with the one before the change $j and if so I would consider it valid.

More data: Try modifying this in the validation rules:

'numero'=>'required|integer|min:0|unique:juegos,numero',

It is assumed that the validator is more correct, although at the moment my problem persists.

Here is the driver code:

public function cambiar(Juego $j, CambioJuegoRequest $request){
    $enl=$j->enlaces;
    foreach($enl as $e)
        $e->delete();
    if(!empty($request->foto)){
        $j->limpiarImagen();
        $foto=str_random(30).'+'.$request->file('foto')->getClientOriginalName();
        $request->file('foto')->move('storage',$foto);
        $j->foto=$foto;
    }

    $j->numero=$request->numero;
    $j->agrupacion_id=$request->agrupacion;
    $j->nombre=$request->nombre;
    $j->materiales=$request->materiales;
    $j->organizacion=$request->organizacion;
    $j->desarrollo=$request->desarrollo;
    $j->observaciones=$request->observaciones;
    $j->variantes=$request->variantes;

    $j->save();

    foreach ($request->capacidad as $capa)
        Enlace::create([
            'juego_id'=>$j->id,
            'contenido_id'=>$capa
        ]);

    return back()->with('message',['success','Juego modificado exitosamente.']);
}
    
asked by Miguel Alparez 12.07.2018 в 18:14
source

2 answers

2

I think I have understood your query, you can achieve what you want to do by adding a custom Rule and then applying that Rule in the validation of the Form Request:

1. Create the Rule

php artisan make:rule CustomRule

2. Edit the rule created in app / Rules

namespace App\Rules;
namespace App\Juego; //suponiendo que en esa carpeta esta la clase Juego

use Illuminate\Contracts\Validation\Rule;

class CustomRule implements Rule
{

    protected $juegoId;

    //va a recibir el id del juego cuando la llamamos para poder hace el chequeo
    public function __construct($id)
    {
        $this->juegoId = $id
    }

    //Acá haces la validación, (creo que esta es la que queres hacer).
    public function passes($attribute, $value)
    {
        $juego = Juego::find($this->juegoId);

        if(juego)
            return juego->numero == $value;
        else
            return true;
    }

    public function message()
    {
        return 'El campo :attribute no coincide';
    }
}

3. I would add an input type with the id of the game to the form so I can know what game it refers to for validation

<input type="hidden" name="id" value="{{$j->id}}">

4. You apply this rule in the validation of the field and you pass the id that arrives in the Request by the input type hidden added in the previous step

public function rules(){
    return[
        'numero'=> ['required', 'integer', 'min:0', new CustomRule($this->request->input('id')],
        'nombre'=>'required',
        'materiales'=>'required',
        'organizacion'=>'required',
        'desarrollo'=>'required',
        'observaciones'=>'required'
    ];
}

It's not 100% tested, but I think it should work.

    
answered by 16.07.2018 / 19:19
source
1

You can have the validator return some rules or others according to the method you receive:

public function rules()
    {
        if (\Request::isMethod('put')) {
            return [
                'numero' => 'required|integer|min:0|unique:juegos,numero',
                'nombre' => 'required',
                'materiales' => 'required',
                'organizacion' => 'required',
                'desarrollo' => 'required',
                'observaciones' => 'required'
            ];
        } else {
            return [
                'nombre' => 'required',
                'materiales' => 'required',
                'organizacion' => 'required',
                'desarrollo' => 'required',
                'observaciones' => 'required'
            ];
        }
    }

Then you can complicate everything you want.

    
answered by 18.07.2018 в 09:41