Unique two columns in laravel - php

I'm working with laravel 5.6 I have this table
users_groups table
with these columns user_id reference to users auto increment id and group_id reference to group auto increment id in groups table
Now I'm trying to validate the entry of data to be unique value for both columns together, but it can't be user_id and group_id the same in the table.
I found this code and tried it:
$validatedData = $request->validate([
'user_id' => 'required|unique_with:users_groups,group_id',
'group_id' => 'required|unique_with:users_groups,user_id',
]);
It gave me this error:
Method Illuminate\Validation\Validator::validateUniqueWith does not exist.
Any help please?

I believe what you're looking for is this:
// Haven't tried this code, but it should be pretty close to what you're looking for
use Illuminate\Validation\Rule;
$validatedData = $request->validate([
'user_id' => [
'required',
Rule::unique('users_groups')->where(function ($query) {
return $query->where('group_id', $request->group_id);
})
],
'group_id' => [
'required',
Rule::unique('users_groups')->where(function ($query) {
return $query->where('user_id', $request->user_id);
})
]
]);

The correct way to validate against a table in a database is to use unique:table name,column
for your case it should be
$validatedData = $request->validate([
'user_id' => 'required|unique:users_groups,group_id',
'group_id' => 'required|unique:users_groups,user_id',
]);
see laravel docs

you can use this
'user_id' => [
'required',
Rule::unique('users_groups')->where(function ($query) {
return $query->where('group_id', \request()->input('group_id'));
})
],
'group_id' => [
'required',
Rule::unique('users_groups')->where(function ($query) {
return $query->where('user_id', \request()->input('user_id'));
})
],

All of the above answers are correct and code can still be simplified
'user_id' => [
'required',
Rule::unique('users_groups')->where('group_id', request('group_id'))
],
'group_id' => [
'required',
Rule::unique('users_groups')->where('user_id', request('user_id'))
],

Related

How to save data from result where eloquent Laravel

I want to save data returned from 'where' eloquent laravel.
My code:
public function duplicate_save(Request $request){
$this->validate($request, [
'bulan_from' => 'required',
'tahun_from' => 'required',
'bulan_to' => 'required',
'tahun_to' => 'required',
]);
$realisasi_keuangan = RealisasiKeuangan::where('bulan', $request->bulan_from)->where('tahun', $request->tahun_from)->get();
RealisasiKeuangan::create($realisasi_keuangan);
return redirect()->route('apps.realisasi-keuangan.index');
}
But the code return error
Illuminate\Database\Eloquent\Builder::create(): Argument #1 ($attributes) must be of type array, App\Models\RealisasiKeuangan given

Laravel pivot of users_filmscore, ¿How I can check if the user already has scored the film and how to update the relationship attributes?

So, I have a pivot table called user_filmscores, where the users can ''follow (watching, dropped, hold-on...)'' a film and add a rating on it.
In the userController I have this function:
public function userFilm(Request $request){
$data = $request->all();
$validator=Validator::make($data,[
'user_id' => 'required',
'film_id' => 'required',
'state' => 'required',
'score' => 'nullable'
]);
if($validator->fails()){
return response()->json([
'ok' => false,
'error' => $validator->messages(),
]);
}
$film = Film::find($data['film_id']);
$user = User::find($data['user_id']);
$filmId=$data['film_id'];
$userId=$data['user_id'];
//Check if the relationship exists (I tried many methods but always the same result with false)
/*$hasFilm = User::where('id', $data['user_id'])->whereHas('film', function ($q) use ($filmId) {
$q->where('id', $filmId);
})->exists();*/
$hasFilm = $user->film()->where('film_id', '=', $filmId)->exists();
/*$user->film()->sync($film->getKey(), [
'film_id' => $data['film_id'],
'user_id' => $data['user_id'],
'state' => $data['state'],
'score'=> $data['score']
]);*/
if(User::where('id', $userId)->where('id')){
$user->film()->attach($film->getKey(), [
'film_id' => $data['film_id'],
'user_id' => $data['user_id'],
'state' => $data['state'],
'score'=> $data['score']
]);
}else{
$user->film()->detach($film->getKey());
}
}
In the final part of the code, I want to check if the relationship between the user and the film exists, to make an action or another. But when I try to check if the relationship exists, it always returns me a false.
I thought to do it like, if there is a relationship, first delete the old relationship, and then create a new one.
I don't know if there is a better way to do it.
User model has this function:
public function film(){
return $this->belongsToMany('App\Models\Film', 'user_filmscores', 'user_id', 'film_id', 'state', 'score');
}
Film model has this function:
public function user(){
return $this->belongsToMany('App\Models\Film', 'user_filmscores', 'film_id', 'user_id', 'state', 'score');
}
Users table:
Films table:
User_filmscores table:

How to properly update a model on laravel? Method Illuminate\Database\Eloquent\Collection::update does not exist

I made a page for a user to update his company information, all companies default values are null, when a user is created. When a user fills the information, i get this error:
Method Illuminate\Database\Eloquent\Collection::update does not exist
I am sure this error is because of my CompanyController#edit
public function edit(Request $request)
{
$this->validate($request, [
'company_name' => 'alpha|max:50',
'phone' => 'integer|max:50',
'gst_hst_number' => 'integer|max:50',
'country' => 'alpha|max:50',
]);
$companies = Company::where('id', Auth::user()->id)->get();
$companies->update([
'company_name' => $request->input('company_name'),
'phone' => $request->input('phone'),
'gst_hst_number' => $request->input('gst_hst_number'),
'country' => $request->input('country')
]);
return redirect()->route('company.index')->with('info', 'Company information was updated.');
}
I am stuck quite some time on this issue, would gladly apriciate help and information how to properly update my company models fillable fields.
‌As the error message says, you are using the update method on a collection, you have to change the select query to this:
$companies = Company::where('id', Auth::user()->id)->first();
Because the get() method returns a collection, not a single record.
Try this. ->get() is for multiple collections here you can directly update your records.
$companies = Company::where('id', Auth::user()->id)->update([
'company_name' => $request->input('company_name'),
'phone' => $request->input('phone'),
'gst_hst_number' => $request->input('gst_hst_number'),
'country' => $request->input('country')
]);;
Your using update method on collection, but collection doesn't have update method,
what you need is remove the get(), so you can use update method on eloquent builder:
$companies = Company::where('id', Auth::user()->id);
$companies->update([
'company_name' => $request->input('company_name'),
'phone' => $request->input('phone'),
'gst_hst_number' => $request->input('gst_hst_number'),
'country' => $request->input('country')
]);

How to make Custom Validation rule for unique Array dependent on other field laravel

I have working on Laravel 5.6. I have 4 dependent unique columns but don't know how to validate these dependent columns
here is my migration for unique constrain:
$table->unique(array('lvl4','document_type','nature_id','type_id'),'u_coa_lvl4_asn_dnt_uk');
lvl4 is array.
Thanks in advance
You can try manaully validating with something like this:
$data = [
'lvl4' => 'Level 4',
'document_type' => 'Some type',
'nature_id' => 1,
'type_id' => 7,
];
$validator = Validator::make($data, [
'data.lvl4' => [
'required',
Rule::unique('your_table')->where(function ($query) use($data) {
return $query->where('lvl4', $data['lvl4'])
->where('document_type', $data['document_type'])
->where('nature_id', $data['nature_id'])
->where('type_id', $data['type_id']);
}),
],
]);
if($validator->fails()) {
// it fails validation ...
}
This is untested, but something like this should work for you.
https://laravel.com/docs/5.6/validation#rule-unique

Laravel unique validation on multiple columns

I have 2 columns in table servers.
I have columns ip and hostname.
I have validation:
'data.ip' => ['required', 'unique:servers,ip,'.$this->id]
This working only for column ip. But how to do that it would work and for column hostname?
I want validate data.ip with columns ip and hostname.
Because can be duplicates in columns ip and hostname, when user write ip.
You can use Rule::unique to achieve your validation rule
$messages = [
'data.ip.unique' => 'Given ip and hostname are not unique',
];
Validator::make($data, [
'data.ip' => [
'required',
Rule::unique('servers')->where(function ($query) use($ip,$hostname) {
return $query->where('ip', $ip)
->where('hostname', $hostname);
}),
],
],
$messages
);
edit: Fixed message assignation
The following will work on the create
'data.ip' => ['required', 'unique:servers,ip,'.$this->id.',NULL,id,hostname,'.$request->input('hostname')]
and the following for the update
'data.ip' => ['required', 'unique:servers,ip,'.$this->id.','.$request->input('id').',id,hostname,'.$request->input('hostname')]
I'm presuming that id is your primary key in the table. Substitute it for your environment.
The (undocumented) format for the unique rule is:
table[,column[,ignore value[,ignore column[,where column,where value]...]]]
Multiple "where" conditions can be specified, but only equality can be checked. A closure (as in the accepted answer) is needed for any other comparisons.
Laravel 5.6 and above
Validation in the controller
The primary key (in my case) is a combination of two columns (name, guard_name)
I validate their uniqueness by using the Rule class both on create and on update method of my controller (PermissionsController)
PermissionsController.php
<?php
namespace App\Http\Controllers;
use App\Permission;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;
use App\Http\Controllers\Controller;
class PermissionsController extends Controller
{
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
request()->validate([
'name' => 'required|max:255',
'guard_name' => [
'required',
Rule::unique('permissions')->where(function ($query) use ($request) {
return $query
->whereName($request->name)
->whereGuardName($request->guard_name);
}),
],
],
[
'guard_name.unique' => __('messages.permission.error.unique', [
'name' => $request->name,
'guard_name' => $request->guard_name
]),
]);
Permission::create($request->all());
flash(__('messages.permission.flash.created'))->success();
return redirect()->route('permission.index');
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, Permission $permission)
{
request()->validate([
'name' => 'required|max:255',
'guard_name' => [
'required',
Rule::unique('permissions')->where(function ($query) use ($request, $permission) {
return $query
->whereName($request->name)
->whereGuardName($request->guard_name)
->whereNotIn('id', [$permission->id]);
}),
],
],
[
'guard_name.unique' => __('messages.permission.error.unique', [
'name' => $request->name,
'guard_name' => $request->guard_name
]),
]);
$permission->update($request->all());
flash(__('messages.permission.flash.updated'))->success();
return redirect()->route('permission.index');
}
}
Notice in the update method i added an additional query constraint [ whereNotIn('id', [$permission->id]) ] to ignore the current model.
resources/lang/en/messages.php
<?php
return [
'permission' => [
'error' => [
'unique' => 'The combination [":name", ":guard_name"] already exists',
],
'flash' => [
'updated' => '...',
'created' => '...',
],
]
]
The flash() method is from the laracasts/flash package.
Table
server
Field
id primary key
ip should be unique with hostname
hostname should be unique with ip
Here I validate for Ip and the hostname should be unique.
use Illuminate\Validation\Rule;
$ip = '192.168.0.1';
$host = 'localhost';
While Create
Validator::make($data, [
'ip' => [
'required',
Rule::unique('server')->where(function ($query) use($ip,$host) {
return $query->where('ip', $ip)->where('hostname', $host);
});
],
]);
While Update
Add ignore after RULE
Validator::make($data, [
'ip' => [
'required',
Rule::unique('server')->where(function ($query) use($ip,$host) {
return $query->where('ip', $ip)->where('hostname', $host);
})->ignore($serverid);
],
]);
This works for me for both create and update.
[
'column_1' => 'required|unique:TableName,column_1,' . $this->id . ',id,colum_2,' . $this->column_2
]
Note: tested in Laravel 6.
Try this rule:
'data.ip' => 'required|unique:servers,ip,'.$this>id.'|unique:servers,hostname,'.$this->id
With Form Requests:
In StoreServerRequest (for Create)
public function rules() {
'ip' => [
'required',
Rule::unique('server')->where(function ($query) {
$query->where('ip', $this->ip)
->where('hostname', $this->host);
})
],
}
public function messages() {
return [
'ip.unique' => 'Combination of IP & Hostname is not unique',
];
}
In UpdateServerRequest (for Update)
Just Add ignore at the end
public function rules() {
'ip' => [
'required',
Rule::unique('server')->where(function ($query) {
$query->where('ip', $this->ip)
->where('hostname', $this->host);
})->ignore($this->server->id)
],
}
This is the demo code. It would help you much better. I tried covering both insert and update scenarios.
Inside app/Http/Providers/AppServiceProvider.php
Validator::extend('uniqueOfMultiple', function ($attribute, $value, $parameters, $validator)
{
$whereData = [
[$attribute, $value]
];
foreach ($parameters as $key => $parameter) {
//At 0th index, we have table name
if(!$key) continue;
$arr = explode('-', $parameter);
if($arr[0] == 'except') {
$column = $arr[1];
$data = $arr[2];
$whereData[] = [$column, '<>', $data];
} else {
$column = $arr[0];
$data = $arr[1];
$whereData[] = [$column, $data];
}
}
$count = DB::table($parameters[0])->where($whereData)->count();
return $count === 0;
});
Inside app/Http/Requests/Something/StoreSometing.php
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'name' => 'required|max:225|uniqueOfMultiple:menus,location_id-' . $this->get('location_id', 'NULL') . ',language_id-' . $this->get('language_id', 1),
'location_id' => 'required|exists:menu_location,id',
'order' => 'digits_between:0,10'
];
}
Inside app/Http/Requests/Something/UpdateSomething.php
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'name' => 'required|max:225|uniqueOfMultiple:menus,location_id-' . $this->get('location_id', 'NULL') . ',language_id-' . $this->get('language_id', 'NULL') . ',except-id-' . $this->route('id', 'NULL'),
'location_id' => 'required|exists:menu_location,id',
'order' => 'digits_between:0,10'
];
}
Inside resources/lang/en/validation.php
'unique_of_multiple' => 'The :attribute has already been taken under it\'s parent.',
Here in this code, the custom validation used is uniqueOfMultiple. The first argument passed is the table_name i.e menus and all other arguments are column_name and are comma-separated. The columns are used here, name (primary column), location_id, language_id and one except-for column for the update case, except-id. The value passed for all three is - separated.
This works for me for both create and update.
in your ServerUpdateRequest or ServerCreateRequest class
public function rules()
{
return [
'column_1' => 'required|unique:TableName,column_1,' . $this->id . ',id,colum_2,' . $this->column_2 . ',colum_3,' . $this->column_3,
];
}
This command run background a aggregate Sql like this
select
count(*) as aggregate
from
`TableName`
where
`column_1` = <postedColumn1Value>
and `id` <> idValue
and `column_2` = <postedColumn2Value>
and `column_3` = <postedColumn3Value>
tested in Laravel 9. and it works
Note: if you want to see background sql for debugging (For example, to check if the request values are empty[$this->]) , especially you have to write wrong code, For example, you may enter a filed name incorrectly.
for me laravel 8 this works
$req->validate([
'house_no' => [
Rule::unique('house')
->where('house_no', $req->input('house_no'))
->where('ward_no', $req->input('ward_no'))
],
]);
The following code worked nicely for me at Laravel 8
Create:
'required|unique:TableName,column_1,' . $this->column_1 . ',id,colum_2,' . $this->column_2,
Example:
public function store(Request $request)
{
$union = auth()->user()->union_id;
$request->validate([
'holding_no' => 'required|integer|unique:holding_taxes,holding_no,' . $request->holding_no . ',id,union_id,' . $union,
]);
}
Update:
'required|unique:TableName,column_1,' . $this->id . ',id,colum_2,' . $this->column_2,
Example:
public function update(Request $request, $id)
{
$union = auth()->user()->union_id;
$request->validate([
'holding_no' => 'required|unique:holding_taxes,holding_no,' . $id . ',id,union_id,'.$union,
]);
}
Simple solution with call back query
Rule::unique('users')->where(fn ($query) => $query->where(['project_id'=> request()->project_id, 'code'=> request()->code ])),
public function store(Request $request)
{
$this->validate($request, [
'first_name' => 'required|regex:/^[\pL\s\-]+$/u|max:255|unique:contacts,first_name, NULL,id,first_name,'.$request->input('last_name','id'),
'last_name'=>'required|regex:/^[\pL\s\-]+$/u|max:255|unique:contacts,last_name',
'email' => 'required|email|max:255|unique:contacts,email',
'job_title'=>'required',
'city'=>'required',
'country'=>'required'],
[
'first_name.regex'=>'Use Alphabets Only',
'email.unique'=>'Email is Already Taken.Use Another Email',
'last_name.unique'=>'Contact Already Exist!. Try Again.',
]
);

Categories