Skip to content
Advertisement

How to validate a unique field on a record update

I am recently started a laravel project to control some activities, but I am currently having issues with the validation specifically when updating a specific record on a table that contains unique values

A couple of notes a started this project a couple of days of the launch of laravel 8 last month so perhaps there some changes that are afecting me.

These are my migrations

The first one is a user with its data, …

<?php

use IlluminateDatabaseMigrationsMigration;
use IlluminateDatabaseSchemaBlueprint;
use IlluminateSupportFacadesSchema;
use IlluminateSupportFacadesDB; //para hacer insersion

class CrearTablaUsuarios extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('usuarios', function (Blueprint $table) 
        {
            $table->increments('id_usuario');
            $table->unique('id_usuario');
            $table->string('nombre_usuario',255);
            $table->string('apellido_usuario',255);
            $table->string('foto_usuario', 255);
            $table->string('alias',255);
            $table->unique('alias');
            $table->string('contraseña',255);
            $table->text('respuesta_pregunta');
            $table->string('telefono_usuario',255);
            $table->unique('telefono_usuario');
            $table->text('correo');
            $table->unique('correo');
            $table->integer('id_tipo_usuario')->unsigned();
            $table->foreign('id_tipo_usuario')->references('id_tipo_usuario')->on('tipos_usuarios')->onDelete('cascade');
            $table->integer('id_cargo_usuario')->unsigned();
            $table->foreign('id_cargo_usuario')->references('id_cargo_usuario')->on('cargos_usuarios')->onDelete('cascade');
            $table->boolean('estado_usuario');
            $table->date('fecha_registro');
            $table->date('fecha_retiro')->nullable();
        });

       
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {

        Schema::dropIfExists('usuarios');
    }
}

Second is a table to describe user types …

<?php

use IlluminateDatabaseMigrationsMigration;
use IlluminateDatabaseSchemaBlueprint;
use IlluminateSupportFacadesSchema;
use IlluminateSupportFacadesDB; //para hacer insersion

class CrearTablaTiposUsuarios extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('tipos_usuarios', function (Blueprint $table) {
            $table->increments('id_tipo_usuario');
            $table->unique('id_tipo_usuario');
            $table->string('nombre_tipo_usuario', 255);
            $table->unique('nombre_tipo_usuario');
            $table->text('descripcion_tipo_usuario');
        });

           // Insert some stuff
        DB::table('tipos_usuarios')
                ->insert(
                [ 
                    [
                        'nombre_tipo_usuario' => 'Administrador',
                        'descripcion_tipo_usuario' => 'Este tipo de usuario se encarga de manejar la aplicación y tiene control total, ademas de ser el unico que puede crear usuarios'
                    ],
                    [
                        'nombre_tipo_usuario' => 'Supervisor',
                        'descripcion_tipo_usuario' => 'Se encarga de ver las actividades de los usuarios , ademas puede agregar clientes y puede asignar clientes a usuarios'
                    ],
                    [
                        'nombre_tipo_usuario' => 'Publicador',
                        'descripcion_tipo_usuario' => 'Este tipo de usuario solo puede agregar conteos a las publiaciones de los clientes'
                    ]
                ]);
    }

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

… An a table to describe user positions …

<?php

use IlluminateDatabaseMigrationsMigration;
use IlluminateDatabaseSchemaBlueprint;
use IlluminateSupportFacadesSchema;
use IlluminateSupportFacadesDB; //para hacer insersion

class CrearTablaCargosUsuarios extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('cargos_usuarios', function (Blueprint $table) {
            $table->increments('id_cargo_usuario');
            $table->unique('id_cargo_usuario');
            $table->string('nombre_cargo', 255);
            $table->unique('nombre_cargo');
            $table->text('descripcion_cargo');
        });

        // Insert some stuff
        DB::table('cargos_usuarios')
                   ->insert(
        [ 
            [
                'nombre_cargo' => 'Gerente',
                'descripcion_cargo' => 'Es el encargado de manejar la empresa de y todas las labores ejecutivas'
            ],
            [
                'nombre_cargo' => 'Programador',
                'descripcion_cargo' => 'Se encarga de dar soporte tecnico, desarrolla sitios web y aplicaciones.'
            ],
            [
                'nombre_cargo' => 'Diseñador',
                'descripcion_cargo' => 'Realiza diversos trabajos como diseño de post, logos y otros.'
            ]
        ]);
    }

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

This last tables must be migrate before "usuarios" to about issues

This is my model

...
<?php

namespace AppModels;

use IlluminateDatabaseEloquentFactoriesHasFactory;
use IlluminateDatabaseEloquentModel;

class usuarios extends Model
{
    use HasFactory;
    public $timestamps = false; //Esto es necesario para que no se produzcan errores de insersción ya que laravel los usa por predeterminado
    
    /**
     * The table associated with the model.
     *
     * @var string
     */
    protected $table = 'usuarios';
    
    /**
     * The primary key associated with the table.
     *
     * @var string
     */
    protected $primaryKey = 'id_usuario';


    public function obtener_tipo_usuario()
    {
        return $this->hasOne('AppModelstipos_usuarios', 'id_tipo_usuario', 'id_tipo_usuario');
    }


    public function obtener_cargo_usuario()
    {
        return $this->hasOne('AppModelscargos_usuarios', 'id_cargo_usuario', 'id_cargo_usuario');
    }

    public function suspender_usuario()
    {
        if ($this->estado_usuario == false) 
        {
            return 'Este usuario ya ha sido suspendido';
        }
        else 
        {
            $this->estado_usuario = false;
            $this->fecha_retiro = date("Y-m-d");
            $this->save();
            return 'usuario suspendido';    
        }
    }

    public function activar_usuario()
    {
        if ($this->estado_usuario == true) 
        {
            return 'Este usuario ya esta activo';
        }
        else 
        {
            $this->estado_usuario = true;
            $this->fecha_retiro = null;
            $this->save();
            return 'Usuario dado de alta';
        }

    }

}

this is my ususarios controller

<?php

namespace AppHttpControllers;

use IlluminateHttpRequest;
use AppModelsusuarios;
use DB; 
use IlluminateSupportFacadesStorage; //para almacenar
use IlluminateHttpFile;
use IlluminateValidationRule;

class UsuariosController extends Controller
{

    /**
     * Muestra el formulario para agregar usuarios
     * Este debe estar disponible solo para el administrador
     *
     * @return IlluminateHttpResponse
     */
    public function create()
    {
        $tipos_usuarios = DB::table('tipos_usuarios')->where('nombre_tipo_usuario', '!=' ,'Administrador')->get();
        $cargos_usuarios = DB::table('cargos_usuarios')->get();
        return view('layouts/sistema/usuarios/agregar_usuario', ['tipos_usuarios' => $tipos_usuarios, 'cargos_usuarios' => $cargos_usuarios] );
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  IlluminateHttpRequest  $solicitud
     * @return IlluminateHttpResponse
     */
    public function store(Request $solicitud)
    {

        $solicitud->validate([
            'archivo_foto_usuario' =>['required', 'mimes:jpeg,png, webp,jpg', 'dimensions:min_width=50,min_height=50,max_width=200,min_height=200'],

            'nombre_usuario' => ['required', 'min:3', 'max:255'],
            'apellido_usuario' =>  ['required', 'min:3', 'max:255'],

            'telefono_usuario' => ['required', 'regex:/^s*(?:+?(d{1,3}))?[-. (]*(d{3})[-. )]*(d{3})[-. ]*(d{4})(?: *x(d+))?s*$/','unique:usuarios,telefono_usuario' ],
    

            'alias_usuario' =>  ['required', 'min:3', 'max:255','unique:usuarios,alias'],

            'contraseña_usuario' =>  ['required','min:8','regex:/^.*(?=.{3,})(?=.*[a-zA-Z])(?=.*[0-9])(?=.*[dx])(?=.*[!$#%]).*$/'],

            'correo_usuario' => ['required', 'regex:/[a-z0-9._%+-]@manilastudio.com$/', 'unique:usuarios,correo'], 

            'tipo_usuario' => 'required',
            'cargo_usuario' => 'required',
        ],  [
            'archivo_foto_usuario.required' => 'Se necesita una imagen en formato compatible',
            'archivo_foto_usuario.mimes' => 'Formato de imagen no soportado',
            'archivo_foto_usuario.dimensions' => 'La imagen debe ser de mimino 50x50 y maximo 200x200',

            'nombre_usuario.required' => 'Campo requerido, introduzca al menos 4 caracteres.',
            'nombre_usuario.min' => 'Campo requerido, introduzca al menos 4 caracteres.',

            'apellido_usuario.required' => 'Campo requerido, introduzca al menos 4 caracteres.',
            'apellido_usuario.min' => 'Campo requerido, introduzca al menos 4 caracteres.',

            'telefono_usuario.required' => 'Introduza un numero teléfonico valido',
            'telefono_usuario.regex' => 'El formato debe ser +50512345678',
            'telefono_usuario.unique' => 'Este número ya esta en uso',

            'alias_usuario.required' => 'Campo requerido, introduzca al menos 4 caracteres.',
            'alias_usuario.min' => 'Campo requerido, introduzca al menos 4 caracteres.',
            'alias_usuario.unique' => 'Esta alias ya esta en uso',

            'contraseña_usuario.required' => 'Campo requerido, introduzca al menos 8 letras, con números o caracteres',
            'contraseña_usuario.min' => 'Campo requerido, introduzca al menos 8 letras, con números o caracteres.',
            'contraseña_usuario.regex' => 'La contraseña temporal debe tener letras o números y caracteres',

            'correo_usuario.regex' => 'El correo debe usar el dominio manilastudio.com',
            'correo_usuario.required' => 'Se necesita asignar un correo electronico',
            'correo_usuario.unique' => 'Este correo ya esta en uso'
        ]);

        $nuevo_usuario = new usuarios();

        $nuevo_usuario->nombre_usuario = $solicitud->input('nombre_usuario');
        $nuevo_usuario->apellido_usuario = $solicitud->input('apellido_usuario');

       /**Guardar en un directorio */
        if ($solicitud->hasFile('archivo_foto_usuario')) 
        {
            $nuevo_usuario->foto_usuario  = $solicitud->archivo_foto_usuario->store('img/usuarios', 'public');
            $solicitud->file('archivo_foto_usuario')->store( 'img/usuarios/');
        }
        else
        {
            $nuevo_usuario->foto_usuario = 'img/usarios/user.png';
        }

        
        $nuevo_usuario->alias = $solicitud->input('alias_usuario');
        $nuevo_usuario->contraseña = $solicitud->input('contraseña_usuario');
        $nuevo_usuario->telefono_usuario = $solicitud->input('telefono_usuario');
        $nuevo_usuario->correo = $solicitud->input('correo_usuario');
        $nuevo_usuario->id_tipo_usuario = $solicitud->input('tipo_usuario');
        $nuevo_usuario->id_cargo_usuario = $solicitud->input('cargo_usuario');
        $nuevo_usuario->fecha_registro = date("Y-m-d");
        $nuevo_usuario->fecha_retiro = null;
        $nuevo_usuario->respuesta_pregunta = 'hola';
        $nuevo_usuario->estado_usuario = true;
        $nuevo_usuario->save();

        return redirect('/usuarios');


    }


    /**
     * Show the form for editing the specified resource.
     *
     * @param  AppModelsusuarios $id_usuario
     * @return IlluminateHttpResponse
     */
    public function edit(usuarios $usuario)
    {
      //  $usuario = usuarios::find($usuario);
        $tipos_usuarios = DB::table('tipos_usuarios')->where('nombre_tipo_usuario', '!=' ,'Administrador')->get();
        $cargos_usuarios = DB::table('cargos_usuarios')->get();
      
       return view('layouts/sistema/usuarios/editar_usuario', ['usuario' => $usuario, 'tipos_usuarios' => $tipos_usuarios, 'cargos_usuarios' => $cargos_usuarios]);
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  IlluminateHttpRequest  $request
     * @param  AppModelsusuarios $user
     * @return IlluminateHttpResponse
     */
    public function update(Request $solicitud, usuarios $usuario)
    {   
       // $usuario = usuarios::findOrFail($id_usuario);
       // dd($usuario->id_usuario);
       $valido =  $solicitud->validate([
            'estado_usuario' =>['required'],
            'archivo_foto_usuario' =>['required', 'mimes:jpeg,png, webp,jpg', 'dimensions:min_width=50,min_height=50,max_width=200,min_height=200'],

            'nombre_usuario' => ['required', 'min:3', 'max:255'],
            'apellido_usuario' =>  ['required', 'min:3', 'max:255'],

            'telefono_usuario' => ['required', 'regex:/^s*(?:+?(d{1,3}))?[-. (]*(d{3})[-. )]*(d{3})[-. ]*(d{4})(?: *x(d+))?s*$/', Rule::unique('usuarios')->ignore($usuario) ],
 

            'alias_usuario' =>  ['required','min:3','max:255',Rule::unique('usuarios')->ignore($usuario)], 

            'contraseña_usuario' =>  ['required','min:8','regex:/^.*(?=.{3,})(?=.*[a-zA-Z])(?=.*[0-9])(?=.*[dx])(?=.*[!$#%]).*$/', Rule::unique('usuarios')->ignore($usuario)],

            'correo_usuario' => ['required', 'regex:/[a-z0-9._%+-]@manilastudio.com$/', /*'unique:usuarios,correo'*/ Rule::unique('usuarios')->ignore($usuario)], 

            'tipo_usuario' => 'required',
            'cargo_usuario' => 'required',
        ],  
        [
            'estado_usuario.required' => "Debe fijarse un estado para este usuario",

           'archivo_foto_usuario.required' => 'Se necesita una imagen en formato compatible',
            'archivo_foto_usuario.mimes' => 'Formato de imagen no soportado',
            'archivo_foto_usuario.dimensions' => 'La imagen debe ser de mimino 50x50 y maximo 200x200',

            'nombre_usuario.required' => 'Campo requerido, introduzca al menos 4 caracteres.',
            'nombre_usuario.min' => 'Campo requerido, introduzca al menos 4 caracteres.',

            'apellido_usuario.required' => 'Campo requerido, introduzca al menos 4 caracteres.',
            'apellido_usuario.min' => 'Campo requerido, introduzca al menos 4 caracteres.',

            'telefono_usuario.required' => 'Introduza un numero teléfonico valido',
            'telefono_usuario.regex' => 'El formato debe ser +50512345678',
            'telefono_usuario.unique' => 'Este número ya esta en uso',

            'alias_usuario.required' => 'Campo requerido, introduzca al menos 4 caracteres.',
            'alias_usuario.min' => 'Campo requerido, introduzca al menos 4 caracteres.',
            'alias_usuario.unique' => 'Esta alias ya esta en uso',

            'contraseña_usuario.required' => 'Campo requerido, introduzca al menos 8 letras, con números o caracteres',
            'contraseña_usuario.min' => 'Campo requerido, introduzca al menos 8 letras, con números o caracteres.',
            'contraseña_usuario.regex' => 'La contraseña temporal debe tener letras o números y caracteres',

            'correo_usuario.regex' => 'El correo debe usar el dominio manilastudio.com',
            'correo_usuario.required' => 'Se necesita asignar un correo electronico',
            'correo_usuario.unique' => 'Este correo ya esta en uso'
        ]);

        $usuario->nombre_usuario = $solicitud->input('nombre_usuario');
        $usuario->apellido_usuario = $solicitud->input('apellido_usuario');

       /**Guardar en un directorio */
        if ($solicitud->hasFile('archivo_foto_usuario')) 
        {
            Storage::disk('public')->delete($usuario->foto_usuario);
            $usuario->foto_usuario  = $solicitud->archivo_foto_usuario->store('img/usuarios', 'public');
            $solicitud->file('archivo_foto_usuario')->store( 'img/usuarios/');
        }
        else
        {
            $usuario->foto_usuario = 'img/usarios/user.png';
        }

       // dd($solicitud->hasFile('archivo_foto_usuario'));
        
        $usuario->alias = $solicitud->input('alias_usuario');
        $usuario->contraseña = $solicitud->input('contraseña_usuario');
        $usuario->telefono_usuario = $solicitud->input('telefono_usuario');
        $usuario->correo = $solicitud->input('correo_usuario');
        $usuario->id_tipo_usuario = $solicitud->input('tipo_usuario');
        $usuario->id_cargo_usuario = $solicitud->input('cargo_usuario');
        $usuario->fecha_registro = date("Y-m-d");

        if ($solicitud->estado_usuario == 0) 
        {
            $usuario->fecha_retiro = date("Y-m-d");
        }
        
        $usuario->respuesta_pregunta = 'hola';
        $usuario->estado_usuario = $solicitud->estado_usuario;

        $usuario->save();


    
        return redirect('/usuarios');
    }
}
...

and this is my view 

...
@section('titulo', 'Modificar datos de Usuario')
<x-master>
<div class="container-fluid mt-5">
    <div class="text-left">
        <h1 class="font-weight-bolder"> 
            Modificar Datos de Usuario
        </h1>
    </div>
    <div class="mt-5">
    <form id="formulario-agregar-usuario" class="form" method="POST" action="/usuarios/{{ $usuario->id_usuario }}" enctype="multipart/form-data">
            @csrf
            @method('PUT')
            <div class="row">
                <div class="col-sm-2">
                    <div class="border rounded p-2 bg-white">
                        <div class="border rounded">
                        <img class="border rounded-circle w-100 img-fluid mr-3" src="/storage/{{$usuario->foto_usuario}}" alt="" title="Nombre Usuario"> 
                        </div>
                    </div>
                    <br>
                    <input class="btn" type="file" name="archivo_foto_usuario">
                    @error('archivo_foto_usuario') <div class="validacion" >{{ $errors->first('archivo_foto_usuario')}}</div> @enderror
                    <div class="mt-4">
                        <input type="radio" name="estado_usuario" id="activo" value="1" @if ($usuario->estado_usuario == 1 ) checked="checked" @endif>
                        <label for="activo" class="font-weight-bolder text-uppercase text-success" >Activo</label><br>
                        <input type="radio" name="estado_usuario" id="suspender" value="0" @if ($usuario->estado_usuario == 0 ) checked="checked"@endif>
                        <label for="suspender" class="font-weight-bolder text-uppercase text-danger">Suspender</label>
                        @error('nombre_usuario') <div class="validacion" >{{ $errors->first('estado_usuario')}}</div> @enderror
                    </div>
                </div>
                <div class="col-sm-6 ml-lg-4 ml-sm-0">
                    <div class="row">
                        <div class="form-group col-md-6">
                            <label for="txtNombre_usuario" class="font-weight-bolder text-uppercase">Nombre Usuario</label>
                            <input  id="txtNombre_usuario" class="form-control" type="text" name="nombre_usuario" value="{{ $usuario->nombre_usuario }}">
                            @error('nombre_usuario') <div class="validacion" >{{ $errors->first('nombre_usuario')}}</div> @enderror
                        </div>
                        <div class="form-group col-md-6">
                            <label for="txtApellido_correo" class="font-weight-bolder text-uppercase">Apellido Usuario</label>
                            <input  id="txtApellido_usuario" class="form-control" type="text" name="apellido_usuario" value="{{ $usuario->apellido_usuario }}">
                            @error('apellido_usuario') <div class="validacion" >{{ $errors->first('apellido_usuario')}}</div> @enderror
                        </div>
                        <div class="form-group col-md-6">
                            <label for="txtTelefono_Usuario" class="font-weight-bolder text-uppercase">Telefono Usuario</label>
                            <input  id="txtTelefono_Usuario" type="tel" class="form-control" name="telefono_usuario" placeholder="ejemplo +505812345678" value="{{ $usuario->telefono_usuario }}">
                            @error('telefono_usuario') <div class="validacion" >{{ $errors->first('telefono_usuario')}}</div> @enderror
                          </div>
                        <div class="form-group col-md-6">
                            <label for="txtemail" class="font-weight-bolder text-uppercase">Correo</label>
                            <input  id="txtemail" class="form-control" type="email"  name="correo_usuario" value="{{ $usuario->correo_usuario }}">
                            @error('correo_usuario') <div class="validacion" >{{ $errors->first('correo_usuario')}}</div> @enderror
                          </div>
                          <div class="form-group col-md-6">
                            <label for="sltTipo_Usuario" class="font-weight-bolder text-uppercase">Tipo de Usuario</label>
                            <select id="sltTipo_Usuario" class="form-control" name="tipo_usuario" >
                                @foreach ($tipos_usuarios as $tipo)
                                <option value="{{$tipo->id_tipo_usuario}}" @if ($tipo->id_tipo_usuario == $usuario->id_tipo_usuario) selected="selected" @endif>{{$tipo->nombre_tipo_usuario }}</option>    
                               @endforeach
                            </select>
                          </div>                         
                          <div class="form-group col-md-6">
                            <label for="sltCargo_Usuario" class="font-weight-bolder text-uppercase">Cargo de Usuario</label>
                            <select id="sltCargo_Usuario" class="form-control" name="cargo_usuario">
                                @foreach ($cargos_usuarios as $cargo)
                                <option value="{{$cargo->id_cargo_usuario}}"  @if ($cargo->id_cargo_usuario == $usuario->id_cargo_usuario) selected="selected" @endif>{{$cargo->nombre_cargo}}</option> 
                                @endforeach 
                            </select>
                          </div>
                          <div class="form-group col-md-6">
                            <label for="txtAlias_usuario" class="font-weight-bolder text-uppercase">Alias Usuario</label>
                            <input  id="txtAlias_usuario" class="form-control" type="text" name="alias_usuario" value="@if (old('alias_usuario') !== null ) {{old('alias_usuario')}}@else {{$usuario->alias}}@endif">
                            @error('alias_usuario') <div class="validacion" >{{ $errors->first('alias_usuario')}}</div> @enderror
                        </div>
                        <div class="form-group col-md-6">
                            <label for="txtcontraseña" class="font-weight-bolder text-uppercase">Contraseña Temporal</label>
                        <input  id="txtcontraseña" class="form-control" type="password" name="contraseña_usuario" value="{{ $usuario->contraseña}}">
                            @error('contraseña_usuario') <div class="validacion" >{{ $errors->first('contraseña_usuario')}}</div> @enderror
                            <div class="validacion" ></div>
                        </div>
                    </div>
                    <div class="text-left">
                        <button type="submit" class="btn btn-primary">Modificar Usuario</button>
                    </div>
                </div>  
            </div>

          </form>
    </div>
</div>
</x-master>

And this is the error that I get

SQLSTATE[42S22]: Column not found: 1054 Unknown column ‘alias_usuario’ in ‘where clause’ (SQL: select count(*) as aggregate from usuarios where alias_usuario = rytertertcc and id_usuario <> 4)

I checked the official laravel documentation https://laravel.com/docs/8.x/validation#rule-unique so I procceded to implement this Rule::unique(‘usuarios’)->ignore($usuario)] so if I update a user alias that is unique piece of data but no the email or telephone that are also uniques pieces of data I should have not this problem,

The other question related to this Laravel: Validation unique on update has not been useful for this matter.

I really appreciate the help if possible, thank you very much.

Advertisement

Answer

Since the input name doesn’t match the column name, you’ll have to pass the column name when you create the rule. Per the documentation, if your database uses a different column than what you’re passing, then you need to pass along the column name as well:

Rule::unique('usuarios', 'alias')->ignore($usuario)
User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement