Mirich
Mirich

Reputation: 351

Apply Unique Validation Check on a Per User Basis

I was creating Login/Registration system for Personal Finance app in Laravel and encountered with the problem of collision of data in database. For example, If registered user with name of UserA creates expense with Name as Car then the registered user with Name as UserB cannot create expense with Name as Car due to that Name column is validated with unique keyword and Car already exists in the databse but was created by another user which is not what I expect. Can you please look at my code and if possible show me where I made mistake. The controller code:

  public function store(Request $request)
    {
        $user_id=auth()->user()->id;
        $user=User::find($user_id);
        $this->validate($request, [
            'Name'=>'required|unique:personal_accountings,Name,'.$user_id,
             'SumOfMoney'=>'numeric'],
                ['Name.required'=>'Name is empty' ,
                'Name.unique'=>'Name already exists']

        );
        $personal= new PersonalAccounting();
        $personal->Name=$request->input('Name');
        $personal->SumOfMoney=$request->input('SumOfMoney');
        $personal->user_id= auth()->user()->id;
        $personal->save(); 

PersonalAcounting model code:

class PersonalAccounting extends Model
{
    public function user(){
        return $this->belongsTo('App\User');
    }
}

User model code:

  public function personalAccounting(){
        return $this->hasMany('App\PersonalAccounting');
  }

Schema::create('personal_accountings', function (Blueprint $table) {
            $table->increments('id');
            $table->string('TypeOfAccounting');
            $table->string('Name');
            $table->integer('SumOfMoney')->unsigned();
            $table->mediumText("Comments")->nullable();
            $table->timestamps();
        });

the next migration

Schema::table('personal_accountings', function($table){
            $table->integer('user_id');
        });

Upvotes: 1

Views: 63

Answers (2)

NineBerry
NineBerry

Reputation: 28559

It is is explained in the documentation under the heading "Adding Additional Where Clauses".

Use a rule like this one according to the example from the documentation:

'Name' => ['required', Rule::unique('personal_accountings')->where(function ($query) {
    return $query->where('user_id', $user_id);
})]

It should also be possible to use the short form:

'Name' => ['required', Rule::unique('personal_accountings')->where('user_id', $user_id)]

For the Rule class to be available, you need to reference the namespace

use Illuminate\Validation\Rule;

Upvotes: 2

TheOni
TheOni

Reputation: 818

It's not a problem of code but a problem of the model you are using for your database. The unique key of the table should be composed by user_id and name, not only by the name column.

Upvotes: 0

Related Questions