Laravel Unique Validation for each user - php

I am running into an issue which I assume is simple, but it has me stumpted and I would appreciate any help.
The issue is I want each user to be able to create ads, User 1 can have one ad called "Test Ad" and user two can have one ad called "Test Ad" What is happening right now is the user can only have one ad called "Test Ad" but if user one has created "Test Ad" then user 2 is not able to because validation is returning that it already exists, but it doesn't exist for that user.
Here is my validation code:
'ad_title' => 'unique:ads,ad_title,user_id|required|min:3|max:128,' . Auth::user()->id,
Thanks for your time!

You can use closure function to apply your custom validation requirement.
Try
[
'ad_title' => [
'required',
'min:3',
'max:128',
function ($attribute, $value, $fail) {
return !! (\DB::table('ads')
->where('user_id', auth()->id())
->get()
->contains('ad_title', $value);
);
},
]
However the logic for this validation is likely to be required at multiple places then it's better to define a custom rule class https://laravel.com/docs/8.x/validation#using-rule-objects

Laravel 5.3 and above
use Illuminate\Validation\Rule;
'email' => Rule::unique('ads')->where(function ($query) {
$query->where('user_id', Auth::id());
})
Laravel 9
use Illuminate\Validation\Rule;
Rule::unique('ads')->where(fn ($query) => $query->where('user_id', Auth::id()))

Related

LARAVEL 9 - Get User ID for user management

I'm creating a users management with Laravel 9, I am an administrator and I would like to change users to admins whenever I like :)
For example this user ->
I wrote this code ->
public function UpdateToAdminAction(Request $request) {
$request->validate([
'type' => 'required|exists:users',
]);
DB::table('users')->update(
['type' => $request->type]
);
return redirect('/gestion-administrateurs');
}
But I cannot update THIS user's type, this code changes ALL users' types lol, it's not what I wanted. Do you know with this code, how can I change THIS user's type ?
Thanks, I hope you'll understand my request ^^
you are selecting all the users by this query DB::table('users'),
assuming you are receiving id in request
you must select one row by adding a where condition DB::table('users')->where('id',$request->id)->update(['type' => $request->type])
You need to pass user ID as route part, or as request param
For example, you may create following route for updating users:
// Dont forget to protect this route with middleware like "can:edit-users"!
Route::post('/user/{id}', 'UserController#update');
then, render in template button to made user admin:
<form method="post" action="/user/{{ $user->id }}">
#csrf
<input type="hidden" name="type" value="admin">
<button type="submit">Make admin</button>
</form>
And create update method:
public function update(Request $request)
{
$request->validate([
'type' => 'required|exists:users',
]);
DB::table('users')
->where('id', $request->id)
->update(
['type' => $request->type]
);
return redirect('/somewhere');
}

Returning HTTP code to POST form in Laravel

I have a very simple view which contains a form. This form contains 2 select fields populated with data from the database.
Let's say the first select contains "Banana", "Apple", "Orange". The second one contains "Burger", "Pizza", "Hot Dog".
I'm submitting the form (POST) and saving the combination in a table of my database. Before actually saving, I'm checking if the combination doesn't already exist. I don't want to save "Banana - Burger" twice.
If the combination already exists I'm returning the following:
session(['error' => 'This combination already exists.']);
return redirect()->back()->withInput();
This brings me back to my form, and shows the error message in a popup.
How can I return the proper HTTP code (409 in this instance)?
You can make changes in your laravel validation for that. Replace your table name and field name in below example.
$data = $request->all();
$request->validate([
'fruits' => [
'required',
Rule::exists('fruits')->where(function ($query) {
$query->where('fruit_name', $data['fruit_name']);
}),
],
'foods' => [
'required',
Rule::exists('foods')->where(function ($query) {
$query->where('food_name', $data['food_name']);
})
]
]);
Hope this will help you.

Table column filled later on

I'm new on Laravel and as I'm playing around with it I encounter this issue.
I have a registration system which worked fine but now I wanted to add a new field in my table (description field for users).
However, this description field, I don't want to be filled when the user signs up, I want the user to fill this when he gets on his profile and updates a modal window.
The problem is, if I let that filed empty, I get an error when I sign up saying that the description filed can't be empty.
This is what I use in my UserController in order to update the description field but I'm not sure if is correct.
public function postDesc(Request $request){
$this->validate($request, [
'description' => 'required|min:20'
]);
$user = User::all();
$user->description = $request->input('description');
$user->save();
return redirect()->route('user.profile.edit');
}
This is how I opened the form:
{!! Form::open(['method' => 'PUT', 'action' => 'UserController#postDesc', 'class' => 'profile-form']) !!}
You use required validation rule, that's why you get the message. You should use different validation rules for register page and profile update form.
Good practice is to create two Request classes and use them for validation of two forms.
In this scenario, I will prefer to keep your description column nullalbe(). So it won't throw an error that description field is empty at the time of sign up.
And later you can update the description field.
public function postDesc(Request $request)
{
$this->validate($request, [
'description' => 'required|min:20'
]);
// Get the logged in user id using auth and then updating description filed
$user = User::where('user_id', Auth::id())
->update([
'description' => $request->description
]);
return redirect()->route('user.profile.edit');
}

Laravel validate unique if id is the same

I have a table/model that contains multiple albums per user.
Is there a way to say that the column title should be unique, but only for the rows that have the same user_id?
Example: http://pastebin.com/8dvM4a1T
As you can see in the example, the user with the id of 2 has created 2 albums, with the same title. I don't want that to be allowed, that's why I'm wondering if there's a way to deny that with the validator from Laravel?
I tried this, but that did not work.
// Validator
$validator = Validator::make($input, [
'title' => 'required|min:1|max:255|unique:galleries,title,'. Auth::user() -> id .',user_id',
'description' => 'min:1|max:255'
]);
Any help appreciated, thanks.
Your code should be something like:
'title' => 'unique:galleries,title,NULL,id,user_id,'.Auth::user() -> id.'',
Or, you can write a custom rule
Reference here
The approach with the default unique rule does not work because the rule expects the column value to be passed as the third parameter, so in your case it would check if the title column is equal to the Auth::user()->id value which is not what you want.
You can create you own custom validation rule by adding the following code to the boot method of the App\Providers\AppServiceProvider class:
Validator::extend('unique_custom', function ($attribute, $value, $parameters)
{
// Get the parameters passed to the rule
list($table, $field, $field2, $field2Value) = $parameters;
// Check the table and return true only if there are no entries matching
// both the first field name and the user input value as well as
// the second field name and the second field value
return DB::table($table)->where($field, $value)->where($field2, $field2Value)->count() == 0;
});
Now you can use the unique_custom (or you can name it whatever you like) rule like so:
$validator = Validator::make($input, [
'title' => 'required|min:1|max:255|unique_custom:galleries,title,user_id,' . Auth::id(),
'description' => 'min:1|max:255'
]);
The rule expects the parameters to be the following:
the 1st parameter to be the table name, which in this case is galleries
the 2nd parameter to be the field name that is supposed to be unique and for which the value comes from the user input, which in this case is title
the 3rd parameter to be the second field name that will be added to the query conditions, which in this case is user_id
the 4th parameter to be the value of the field name passed as the third parameter
Also you can use Auth::id() since that is the short form of Auth::user()->id.
You can read more about Custom Validation rules in the Laravel Documentation.
Laravel 5.3 and above
use Illuminate\Validation\Rule;
'email' => Rule::unique('galleries')->where(function ($query) {
$query->where('user_id', Auth::id());
})
Laravel 9
use Illuminate\Validation\Rule;
Rule::unique('galleries')->where(fn ($query) => $query->where('user_id', Auth::id()))

Laravel 5 - MethodNotAllowedHttpException when validation is false

Always when the validation fails, I get a MethodNotAllowedHttpException
routes.php
Route::post('download', 'UrlController#download');
Route::post('search', 'UrlController#search');
UrlController.php
public function download(DownloadRequest $request)
{
dd($request->all());
}
DownloadRequest.php
public function authorize()
{
return true;
}
public function rules()
{
return [
'format' => 'required|between:1,13'
];
}
name.blade.php
{!! Form::open(['url' => 'download']) !!}
{!! Form::select('format', [
'Please select format',
'FormatGrp1' => [1 => 'best', 'p1','p2', 'p3', 'p4'],
'FormatGrp2' => [6 => 'p5', 'p6']
]) !!}
When "Please select format" is chosen and the form is submitted, I always get this error because "Please select format" has value 0 and i specified values must be between 1 and 13. (Look at DownloadRequest.php)
Thanks for help!
The error didn't come from the validation.
It was because it called the URL to go back and display the errors. And this is the search method.
So cause of the logic in search method the exception has been thrown.
When you have this error, in your if ($validator->fails()) { } consider that you are going to open the view you are working on for the first time, and add ->withErrors($validator)
For example:
public function edit($id)
{
$exams = Exam::all();
return view('exams.index', compact("exams"));
}
...
public function update(Request $request,$id)
{
$validator = Validator::make($request->all(),[
'start' => 'required',
'end' => 'required|after:start'
]);
if ($validator->fails())
{
$exams = Exam::all();
return view('exams.index', compact("exams"))->withErrors($validator);
}
//Your update code if validator not fails
}
I didn't exactly understand what this user was trying to explain as the actual problem or solution - I came across this question as I had the same issue and thought I would describe what I had done in error and how I solved it...
For me, I was building a site where users would submit photos. When the user clicked on the "add photo" it took them to a page where they had to check a box to accept a legal disclaimer. This form with the checkbox was a POST request. After they accepted it they would get re-directed to the photo submission page... WHICH WAS ALSO A FORM WITH A POST REQUEST. This was my issue: back to back POST request pages. If the user entered invalid data on the submission form, or didn't enter data in a field at all Laravel tries to essentially hit the "back button" in your browser and keep the form filled with the data the user did enter. The problem is that the "back" button (or the way the user came to this page) was from a POST request, so it couldn't do it. It gave me the error described above. Once I switched the legal acceptance page to a GET request form and updated the route to match everything started working fine. It was a foolish error on my part, I just hope to mitigate this frustration for others as they are learning to develop in Laravel. Have a great day!

Categories