Laravel request date validation - php

I am beginner webdeveloper / php laravel developer.
I have this request:
class ProductRequest extends FormRequest
{
public function authorize()
{
return true;
}
public function rules()
{
$id = $this->route('product');
return array_merge(
[
'name' => ['required', 'max:255', Rule::unique('products')->ignore($id)->whereNull('deleted_at')],
'slug' => ['required', 'max:255', Rule::unique('products')->ignore($id)->whereNull('deleted_at')],
'price' => ['required', 'numeric'],
'preorder_release_date' => ['required', 'numeric'],
],
$this->generateTranslationsRules()
);
}
private function generateTranslationsRules(): array
{
$rules = [];
foreach (LaravelLocalization::getSupportedLanguagesKeysExceptDefault() as $locale) {
$rules[$locale . '.name'] = ['required', 'max:255'];
$rules[$locale . '.slug'] = ['required', 'max:255'];
}
return $rules;
}
}
It's work fine.
I need to add a requirement for preorder_release_date - the date cannot be earlier than today. How can I write it down?
Please help me

use Laravel validation before
'preorder_release_date' => ['required','date','date_format:Y-m-d','before:today'],
NOTE : date format you need to adjust based on your request
ref link https://laravel.com/docs/8.x/validation#rule-before

Related

DRY: Implementing form requests and JSON:API resource validation in Laravel

Laravel offers two ways to implement request validation:
For forms you can use Validation.
For JSON:API you can use Resource validation
But this two approaches force you to repeat and maintain two validation rules.
What would be the best way to DRY?
Examples
Form validation
Form validation
class HostCreateRequest extends Request
{
public function rules(): array
{
return [
'hostname' => [
'required', 'max:255',
// 'hostname' and 'username' combination must be unique
Rule::unique('hosts')->where(function ($query) {
return $query->where('username', $this->input('username'));
}),
],
'username' => ['required', 'max:255'],
/* More fields' validation */
];
}
}
JSON:API validation
JSON:API resource validation
class HostRequest extends ResourceRequest
{
public function rules(): array
{
$data = $this->validationData();
// Scope the query to only search records that have the proper 'username'.
$unique = Rule::unique('hosts')->where(function ($query) use ($data) {
return $query->where('username', $data['username']);
});
if ($host = $this->model()) {
$unique = $unique->ignore($host);
}
return [
'hostname' => ['required', 'max:255', $unique],
'username' => ['required', 'max:255'],
/* More fields' validation */
'groups' => JsonApiRule::toMany(),
];
}
}

How do you customize the default login error message in laravel 8

I was browsing through the web and looking for solution on how can I modify this error message on Jetstream login:
Inside app/Actions/Fortify there is a file CreateNewUser.php where I can put some validation custom message on each field like this:
public function create(array $input)
{
Validator::make($input, [
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'phone' => ['required', 'string', 'max:17'],
'password' => $this->passwordRules(),
'terms' => Jetstream::hasTermsAndPrivacyPolicyFeature() ? ['required', 'accepted'] : '',
],[
'name.required'=>'Name is required',
'email.required'=>'Email is required',
'phone.required'=>'Phone is required',
])->validate();
However, there is none for Login.php. I search the web and saw something about vendors/laravel/fortify/src/Actions/AttemptToAuthenticate.php but its consist with lots of code where I don't know where to put the customization:
public function handle($request, $next)
{
if (Fortify::$authenticateUsingCallback) {
return $this->handleUsingCustomCallback($request, $next);
}
if ($this->guard->attempt(
$request->only(Fortify::username(), 'password'),
$request->filled('remember'))
) {
return $next($request);
}
$this->throwFailedAuthenticationException($request);
}
Is there an easy way to customize the "The email field is required" to a different custom message in Laravel 8?
Been stuck for a couple of hours.
You can customize FortifyServiceProvider inside App > Providers by using the Fortify::authenticateUsing method and it should be called from the boot method.
public function boot()
{
Fortify::authenticateUsing(function (Request $request) {
$user = User::where('email', $request->email)->first();
if ($user &&
Hash::check($request->password, $user->password)) {
return $user;
} else {
$request->session()->flash('message', 'Invalid!');
return false;
}
});
}
Reference
step 1 go to vendor\laravel\fortify\src\Http\Requests\LoginRequest.php
step 2 in the loginRequest.php you will find two method
public function authorize()
{
return true;
}
public function rules()
{
return [
Fortify::username() => 'required|string',
'password' => 'required|string',
];
}
step 3 add the following method below
public function messages() {
return = [
'email.required' => 'email required',
'password.required' => 'password required'
];
}

dont want to edit particular field which is used in store and update functions

ProductController
public function store()
{
$product = Product::create($this->validateRequest());
return redirect('/product');
}
public function update(Product $product)
{
$product->update($this->validateRequest());
return redirect('/product');
}
private function validateRequest()
{
return request()->validate([
'sub_category_id' => ['required'],
'name' => ['required', 'min:4'],
'code' => ['required', 'alpha_dash','unique:products'],
'description' => ['required', 'min:4'],
'color' => ['required', 'min:3'],
'price' => ['required', 'integer'],
]);
}
here code has unique value from table products. but whenever I edit the form it says code has already taken. so how to execute this without edit the 'code'(its unique).
You can ignore certain ids during the unique check:
use Illuminate\Validation\Rule;
public function store()
{
Product::create($this->validateRequest(new Product()));
return redirect('/product');
}
public function update(Product $product)
{
$product->update($this->validateRequest($product));
return redirect('/product');
}
private function validateRequest(Product $product)
{
return request()->validate([
'sub_category_id' => ['required'],
'name' => ['required', 'min:4'],
'code' => ['required', 'alpha_dash', Rule::unique('products')->ignore($product)],
'description' => ['required', 'min:4'],
'color' => ['required', 'min:3'],
'price' => ['required', 'integer'],
]);
}
Here you either pass the existing model when updating or a new model instance when storing, so the call to $product->id either returns null when storing a new product so no product in the database is ignored, or the id when updating and then only that product is ignored.
From the docs:
Forcing A Unique Rule To Ignore A Given ID:
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. You will probably 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.
To instruct the validator to ignore the user's ID, we'll use the Rule
class to fluently define the rule. In this example, we'll also specify
the validation rules as an array instead of using the | character to
delimit the rules:
use Illuminate\Validation\Rule;
Validator::make($data, [
'email' => [
'required',
Rule::unique('users')->ignore($user->id),
],
]);
Be aware of the following though:
You should never pass any user controlled request input into the
ignore method. Instead, you should only pass a system generated unique
ID such as an auto-incrementing ID or UUID from an Eloquent model
instance. Otherwise, your application will be vulnerable to an SQL
injection attack.
So the problem here is you are using the same rule for creating the product and updating the product.
If you are using the latest Laravel, you may want to read the documentation about form request https://laravel.com/docs/7.x/validation#form-request-validation and create different form request for store and update.
If you still want to use your way, you can try as below
private function validateRequest()
{
$rules = [
'sub_category_id' => ['required'],
'name' => ['required', 'min:4'],
'description' => ['required', 'min:4'],
'color' => ['required', 'min:3'],
'price' => ['required', 'integer'],
];
if (request()->isMethod('store')) {
$rules['code'] = ['required', 'alpha_dash'];
}
return request()->validate($rules);
}
Please tell me whether it works!
Try this, proper and clean code
ProductController
use Illuminate\Validation\Rule; // add this
public function store()
{
$product = Product::create($this->validateRequest());
return redirect('/product'); //use route instead of URL
}
public function update(Product $product)
{
$product->update($this->validateRequest($product->id));
return redirect('/product'); //use route instead of URL
}
private function validateRequest($id = null)
{
return request()->validate([
'sub_category_id' => 'required',
'name' => 'required|min:4',
'code' => 'required|alpha_dash|' . Rule::unique('products')->ignore($id),
'description' => 'required|min:4',
'color' => 'required|min:3',
'price' => 'required|integer',
]);
}
Suggest to use Form request validation

Laravel Registration Key with Validation

I'm currently trying to modify the base Laravel Authentication to include the use of a key created in the database, I've included another field named "key" which I've been able to get the registration to check via a model, the issue is that if the key is incorrectly input I haven't been able to let the user know the key is incorrect.
Current RegistrationController.php
protected function validator(array $data)
{
return Validator::make($data, [
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => ['required', 'string', 'min:8', 'confirmed'],
'key' => ['required'],
]);
}
/**
* Handle a registration request for the application.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function register(Request $request)
{
$d = Key::where('key', $request->only(['key'])['key'])->first();
if($d != null){
$this->validator($request->all())->validate();
event(new Registered($user = $this->create($request->all())));
$this->guard()->login($user);
if ($response = $this->registered($request, $user)) {
return $response;
}
return $request->wantsJson()
? new Response('', 201)
: redirect($this->redirectPath());
}
else{
$this->validator($request->all())->validate();
return view('auth.register')->withErrors(['key', 'This key was not found']);
}
}
I've tried to modify the validate method to include same but when testing using same:12345 it looks for a variable called 12345 instead of checking if the key is the same as 12345, how do I change the validation to do what I've done in the register method to check the models instead.

Laravel - Validator::make fails my unique rule

I'm trying to use a validation on 'name' as unique, but to be ignored if the objected that has that same name is the same object being updated.
The Validation keeps failing, can you help me figuring out why?
Validator Function - I'm using same validator function to both create and update and only need to apply the rule on the update.
protected function validator(array $data, Wharehouse $wharehouse = null)
{
//different validations for create and edit
if($wharehouse != null){
return Validator::make($data, [
'name' => ['required', 'string', 'max:255', Rule::unique('wharehouses')->ignore($wharehouse)],
'espacoTotal' => ['required', 'numeric', 'max:60000']
]);
}else{
return Validator::make($data, [
'name' => ['required', 'string', 'max:255', Rule::unique('wharehouses')],
'espacoTotal' => ['required', 'numeric', 'max:60000']
]);
}
}
Validation Call
protected function editById(Request $request)
{
$wharehouse = Wharehouse::find($request->wharehouse_id);
$validation = $this->validator($request->all(),$wharehouse);
if ($validation->fails()) {
return Redirect::to('/wharehouses')->withInput()->withErrors($validation);
} else {
$wharehouse->name = $request->input('name');
$wharehouse->espacoTotal = $request->input('espaco');
$wharehouse->save();
return back()->with('create.success','Armazem actualizado com sucesso.');
}
}
Append the id of the instance currently being updated to the validator.
Pass the id of your instance to ignore the unique validator.
In the validator, use a parameter to detect if you are updating or
creating the resource.
If updating, force the unique rule to ignore a given id: unique:table,column,except,idColumn
//rules
'name' => ['required', 'string', 'max:255', 'unique:users,name,' . $userId],

Categories