I'm using Laravel 8 and the unique validation rule to ensure that a record remains unique, I'm now trying to extend this so that it's unique per user as well, but when expanding the functionality and using the rule in array form it doesn't seem to validate the user ID and instead gives me a integrity constraint violation.
So I have a table called brands, and this table contains two columns in question: brand and user_id, I need to ensure that when storing a record that the brand is unique against the brand column and that the logged in in user's ID the one making the request, e.g:
Two users can have the same brand, but a single user can't have multiples of the same brand.
$validator = Validator::make($request->all(), [
'brand' => [
'required',
'string',
Rule::unique('brands')->where(function ($query) {
return $query->where('user_id', Auth::id());
})
],
'url' => 'required|string',
'telephone' => 'required|string|min:11|max:11'
]);
I've also tried:
'brand' => 'required|string|unique:brands,brand,user_id,' . Auth::id()
What am I missing?
According to the documentation you have to use the ignore() function:
Rule::unique('users')->ignore($user->id),
on your case:
Rule::unique('brands')->ignore($user->id, 'user_id'),
Related
UpdateEntityRequest.php:
'phones' => 'sometimes|nullable|array',
'phones.*.id' => 'sometimes|required|integer|distinct|exists:entity_phones,id,entity_id,'.$this->id,
'phones.*.number' => 'required|alpha_num|max:255|distinct|unique:entity_phones,number,'.$this->id.',entity_id',
entity_phones table:
id, number, entity_id.
unique constraint: (number, entity_id)
EntityRepository.php:
foreach ($attributes['phones'] as $phone) {
if (isset($phone['id'])) {
$entity->phones()->updateOrCreate([
'id' => $phone['id'],
'entity_id' => $entity->id
], $phone);
} else {
$entity->phones()->create($phone);
}
}
My entity can have more than phone associated, but not a repeated number. My intention is to check the unique (entity_id, number) in the UpdateEntityRequest.php so:
If the phone object comes without an id, it should check that the combination of number, entity_id doesn't exists. But the number can exist with other entity_id.
If the request comes with an id, it should check that the combination of number, entity_id doesn't exists only in other ids, but ignore the given id.
I'm having trouble witht the Laravel Unique rule validating only when i want it to make the validation. Any ideas how could I make this solution would be appreciated.
If you need to ignore a given ID during the unique check try using the Rule class to fluently define the rule.
use Illuminate\Validation\Rule;
Validator::make($request_data, [
'number' => [
'required',
'alpha_num', (...all your other rules)
Rule::unique('entity_phones')->ignore($entity_id),
],
]);
You can read more in laravel docs about unique rule in paragraph: Forcing A Unique Rule To Ignore A Given ID.
I ended up doing this:
$phoneIds = $this->input('phones.*.id');
'phones.*.number' =>
[
'required_with:phones',
'alpha_num',
'max:255',
'distinct',
Rule::unique('entity_phones', 'number')
->where('entity_id', $this->id)
->where(function ($query) use ($phoneIds) {
return $query->where('id', '!=', array_shift($phoneIds));
})
],
I'm trying to update two tables in Laravel. But I don't know if you can do this while using an associative array with the help of Object->update($associative-array);
I have made an update sequence in laravel which updates a user and a location in two separate tables with a foreign key in the user table. I tried to update both tables doing update statements with the objects of the tables. I tried this in the following way:
$user->update($attributes);
$user->update($attributes); $location->update($attributes);
But this will only update the user table and skips the location table. The $attributes array contains multiple column data of the table user and location. The array is in order of the first column from the user table to the last column of the location table.
But neither of those tries updated both the tables. They only update user and skips location. As far as I know, is that you can do it this way with an associative array if the array contains the column data in the same order of a table and Laravel does the rest. With only updating the user table it does work, But I want it to work with two tables in the way It works using the update function with the object.
MySQL tables
users:
id
firstname
middlename
lastname
active
email
password
phone
mobile_work
phone_work
gender
position_id
settling_id
location_id
locations:
id
street
house_number
addition
zipcode
city
province
country
public function update(Request $request, User $user, Location $location)
{
$attributes = request()->validate([
'firstname' => 'min:3|max:50',
'middlename' => 'max:50',
'lastname' => 'min:3|max:50',
'active' => 'required',
'email' => 'min:3|max:100',
'gender' => '',
'phone' => 'numeric|min:8',
'mobile_work' => 'numeric|min:8',
'phone_work' => 'numeric|min:8',
'position_id' => '',
'settling_id' => '',
'location_id' => '',
'street' => 'required|min:3',
'house_number' => 'required|numeric',
'addition' => '',
'zipcode' => 'required|min:6|max:7',
'city' => 'required|min:3',
'province' => 'required|min:3',
'country' => '',
]);
$user->update($attributes);
}
If the way I'm trying to do it is impossible, I'd like to hear what the standard approach is in updating two tables within one update sequence.
What you try to do is not quite right. You should try to update the relation as well, and preferably first like
$location->update($locationAttributes);
$user->update($userAttributes);
By the way, it is not quite clear you want to update Location record or you want to associate a new Location to User. If it is latter then you can associate the Location to user like
$user->locations()->attach($locationId);
I made the mistake to not include the locations function from the model User into the update sequence.
User model:
public function locations()
{
return $this->hasOne(Location::class, 'id', 'location_id');
}
I fixed the problem by simply deviding the $attribute array to 2 arrays with their own table column data. I also made a second statement which calls the location function from the model and updates it accordingly.
$user->locations()->update($locationAttributes);
$user->update($attributes);
With $attributes only containing the user information and $locationAttributes only containing the location information.
$locations() refers to the row in the table locations. It knows which row to pick by taking the location_id from the selected user.
I am having issues inserting data into my database tables. I have users table which is has a relation of one to many to school table and region table. That is, users table has foreign keys of school and region tables.
I have created the relations correctly but then when i try to insert values into the database, i get the error.
PS: I have one user(admins) in the user table (the school_id and region_id was inserted accurately) already which i saved through RegisterController. Now, when i sign in with the user(admin) already saved, i want to save other users through the UserController but then i get the error above.
What am i not doing right?. I am only a beginner with database relationship and laravel
General error: 1364 Field 'school_id' and `region_id`doesn't have a default value
meaning the field cannot be empty.
UserController
public function store(UserFormRequest $request)
{
$user = new User(array(
'name' => $request->get('name'),
'email' => $request->get('email'),
'password'=> $request->get('password'),
'phone' => $request->get('phone')
));
$user->save();
}
there are three solutions to your problem.
1
public function store(UserFormRequest $request)
{
$user = new User(array(
'name' => $request->get('name'),
'email' => $request->get('email'),
'password'=> $request->get('password'),
'phone' => $request->get('phone'),
'school_id'=>'you must pass value here',
'region_id'=>'you must pass value here'
));
$user->save();
}
2 Go to phpmyadmin make your school_id,region_id default value NULL. so you are good to go.
MySQL is telling you that those fields can't be empty because they aren't nullable.
To make those fields nullable() in your users migration:
// Your create users table migration
$table->integer('school_id')->nullable();
$table->integer('region_id')->nullable();
(You can add any other properties to these - like index(), unsigned(), or foreign keys, etc.)
I'm using "unique" keyword for validating unique users for employee_id in controllers, in my database there is column called company_id , while adding new user they will be set us some company_id ,when i add new user for my company employee id will be unique for my company itself , if employee_id is 4 for another company and i'm adding 4 for my company it must accept , it will check only for that particular company only.
$this->validate($request,
[
'name' => 'required',
'emp_id' => 'required|unique:users', (Here how can i check for particular company)
'email' => 'required|unique:users',
'role' => 'required',
]);
can anyone please help me ???
You should use the array syntax here and use a "custom" unique rule:
'emp_id' => [ "required", Rule::unique('users')->where(function ($query) use ($request) {
$query->where('emp_id', $request->emp_id)->where("company_id",$request->company_id);
}) ]
Something like this anyway
If emp_id and company_id is in request
'emp_id' => 'required|unique:users,emp_id|unique:users,company_id',
Check in docs : https://laravel.com/docs/master/validation#rule-unique
I assume emp_id and company_id are present in users table and you are sending in request
These are my rules in my class:
class AppointmentsController extends Controller
{
protected $rules = [
'appointment' => ['required', 'min:5'],
'slug' => ['required', 'unique:appointments'],
'description' => ['required'],
'date' => ['required', 'date_format:"Y-m-d H:i"'],
];
This is in the laravel official docs:
Sometimes, you may wish to ignore a given ID during the unique check.
For example, consider an "update profile" screen that includes the
user's name, e-mail address, and location. Of course, you will want to
verify that the e-mail address is unique. However, if the user only
changes the name field and not the e-mail field, you do not want a
validation error to be thrown because the user is already the owner of
the e-mail address. You only want to throw a validation error if the
user provides an e-mail address that is already used by a different
user. To tell the unique rule to ignore the user's ID, you may pass
the ID as the third parameter:
'email' => 'unique:users,email_address,'.$user->id.',user_id'
I tried using this in my rules:
'slug' => ['required', 'unique:appointments,id,:id'],
This indeed ignores the current row BUT it ignores it completely. What I want to accomplish is, I want it to ignore the current row only if the slug is unchanged. When it is changed to something that is already unique in another row, I want it to throw an error.
The Unique validator works like that
unique:table,column,except,idColumn
So in your case, you can do it like that:
Get the id you want to validate against, you can get it from the route or with any other way that works for you; something like that
$id = $this->route('id');
'slug' => ['required','unique:appointments,slug,'.$id],
For example we need to update contact info into Users table.
In my model User I created this static method:
static function getContactDataValidationRules( $idUserToExcept ) {
return [
'email' => 'required|email|max:255|unique:users,email,' . $idUserToExcept,
'pec' => 'required|email|max:255',
'phone' => 'required|regex:/^([0-9\s\-\+\(\)]*)$/|min:8|max:20',
'mobile' => 'required|regex:/^([0-9\s\-\+\(\)]*)$/|min:8|max:20',
'phone2' => 'required|regex:/^([0-9\s\-\+\(\)]*)$/|min:8|max:20',
'recovery_email' => 'required|email|max:255',
];
}
and in my UsersController, into the method that update User I've:
$id = $request->input('id');
$request->validate(User::getContactDataValidationRules( $id ));
:-)