Custom validation rule in Laravel 5 registrar - php

I am using the default Laravel 5 user registration stuff which uses the registrar.php file app/Services/Registrar.php
I need to do a custom validation rule to check that there is some stuff stored in the session otherwise the user shouldn't be able to register.
I have tried creating my own validation rule but it doesn't seem to be getting called. What am I doing wrong?
<?php namespace App\Services;
use App\User;
use Event;
use Validator;
use Illuminate\Contracts\Auth\Registrar as RegistrarContract;
use App\Events\UserRegistered;
use Session;
class Registrar implements RegistrarContract {
/**
* Get a validator for an incoming registration request.
*
* #param array $data
* #return \Illuminate\Contracts\Validation\Validator
*/
public function validator(array $data)
{
Validator::extend('required_images', function($attribute, $value, $parameters)
{
die("rule called");
});
return Validator::make($data, [
'first_name' => 'required_images|required|max:255',
'last_name' => 'required|max:255',
'discount_code' => 'max:255',
'register_email' => 'required|email|confirmed|max:255|unique:users,email',
'register_password' => 'required|confirmed|min:6|max:60'
]);
}
}
Also I have just attached the rule required_images to the first_name field but since it doesn't actually relate to a field in the registration form is there a better way to trigger it?

If you look closely at the validator() function you can see that there's actually a return statement:
public function validator(array $data)
{
return Validator::make($data, [
// ^^^
'first_name' => 'required_images|required|max:255',
'last_name' => 'required|max:255',
// ...
That means your rule never get's registered. You should do it before instead:
public function validator(array $data)
{
Validator::extend('required_images', function($attribute, $value, $parameters)
{
die("rule called");
});
return Validator::make($data, [
'first_name' => 'required_images|required|max:255',
'last_name' => 'required|max:255',
'discount_code' => 'max:255',
'register_email' => 'required|email|confirmed|max:255|unique:users,email',
'register_password' => 'required|confirmed|min:6|max:60'
]);
}

Related

Unique always return already taken in laravel validation

I'm trying to update a company data using CompanyRequest but got an error. Please see my code below and other details.
CompanyRequest.php
<?php
namespace App\Http\Requests;
use Illuminate\Validation\Rule;
use Illuminate\Foundation\Http\FormRequest;
class CompanyRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
if($this->isMethod('PATCH')) {
return [
'name' => [
'required',
'max:255',
Rule::unique('companies')->ignore($this->id)
],
'owner' => 'required|max:255',
'address' => ''
];
}
return [
'name' => 'required|max:255|unique:companies',
'owner' => 'required|max:255',
'address' => ''
];
}
}
CompanyController.php
public function update(Company $company, CompanyRequest $request)
{
return $company->update($request->validated());
}
api.php
Route::patch('company/{company}', [CompanyController::class, 'update'])->name('company.update');
Error
I think you need to use the same property as the route
Rule::unique('companies')->ignore($this->company)
Try something like
'name' => 'unique:companies,name,' . $id,
so basically name is unique, but allow update when id is same.
To tell the unique rule to ignore the user's ID, you may pass the ID as the third parameter:
'name' => 'unique:companies,column,'.$this->id

Laravel dynamic validation

I'm using Laravel and I have a custom validation. I want to pass some value to the validation class and validate it against the DB so I keep all the validation logic in the validation class. Here's my code but the validation error is not triggered:
public function rules() {
$userCode = UserCode::getCode();
$rules = [
'name' => 'required|string',
'email' => 'required|email',
$userCode => 'unique:user_codes,code,'. $userCode
];
return $rules;
}
What am I doing wrong here? the validation is never triggered even if the value $userCode already exists in the DB. The validation is triggered if the request contains bad email for example.
Edit: I have this user_codes table that has a code column that must be kept unique. UserCode::getCode() produces this code. So I also want to check if this code is unique or not in the table user_codes before passing it to the controller. I already have the custom validator but the problem is that I want it to also validate this code. The validator works fine with the other request body. The problem is that this code is not passed from the request body but it is simply generated from another method.
You could do this using a FormRequest class with the prepareForValidation() method. It should look something like this:
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class WhateverRequest extends FormRequest
{
protected function prepareForValidation(): void
{
$this->merge([
'user_code' => UserCode::getCode(),
]);
}
public function rules(): array
{
return [
'name' => 'required|string',
'email' => 'required|email',
'user_code' => 'unique:user_codes,code'
];
}
}
your question is not clear, I understand you have a column named by code
and you want to be unique, you can add usercode to request,
request()->merge(['userCode'=>$userCode]);
then
$rules = [
'name' => 'required|string',
'email' => 'required|email',
'userCode' => 'unique:user_codes,code,'.UserCode::getId().',id'
];
I answered what I understand from your question
Okay start with the following:
php artisan make:rule SomeAwesomeRule
Then edit that created Rule
class SomeAwesomeRule implements Rule
{
/**
* Create a new rule instance.
*
* #return void
*/
public function __construct()
{
//
}
/**
* Determine if the validation rule passes.
*
* #param string $attribute
* #param mixed $value
* #return bool
*/
public function passes($attribute, $value)
{
//some logic that needs to be handled...
}
/**
* Get the validation error message.
*
* #return string
*/
public function message()
{
return __('Some.nice.translated.message');
}
}
And then apply the rule
$rules = [
'name' => 'required|string',
'email' => 'required|email',
'userCode' => new SomeAwesomeRule(#this is a constructor so pass away)
];
see
$rules = [
'name' => 'required|string',
'email' => 'required|email',
'userCode' => 'unique:user_codes,code'
];
//or
$userCode="";
do{
$userCode = UserCode::getCode();
}
while(UserCode::where('code',$userCode)->first());
// after loop you sure the code is unique
$rules = [
'name' => 'required|string',
'email' => 'required|email',
];

How to pass non required fields through FormRequest?

I'm using FormRequest for Validation.
I'm creating record in DB. There a some fields which are not required, how can i get them through FormRequest. At, the moment i'm only getting fields which are in rules() method.
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class CategoryRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'title_tr' => 'required|min:2|max:255',
'description_tr' => 'required',
'parent_id' => 'required',
'seo_title_tr' => 'required',
'meta_description_tr' => 'required'
];
}
public function messages(){
return [
'title_tr.required' => trans('admin.category.validation_errors.title_tr'),
'description_tr.required' => trans('admin.category.validation_errors.description_tr'),
'seo_title_tr.required' => trans('admin.category.validation_errors.seo_title_tr'),
'meta_description_tr.required' => trans('admin.category.validation_errors.meta_description_tr'),
];
}
}
you can use sometimes
Validating When Present In some situations, you may wish to run
validation checks against a field only if that field is present in the
input array. To quickly accomplish this, add the sometimes rule to
your rule list:
public function rules()
{
return [
'username' => 'sometimes',
];
}
You can make it nullable as shown below.
public function rules()
{
return [
// ...
'not_required_field' => 'nullable',
];
}

How to add custom validaton rule to default Validator::make($data... register in laravel?

I have read in the documentation how to create new custom validation rule.
I have made one like the one in the example but to only allow lowercase. The class is creatively named Lowercase.
Now I want to add that to the Validator-list in the RegisterController generated from make:auth. This is the list I want to add it to:
return Validator::make($data, [
'name' => 'required|string|max:255|**ADD MY VALIDATOR HERE**',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:6|confirmed',
]);
Obviously there is something here I am missing... In the documentation it says to use the one I have done like this:
$request->validate([
'name' => ['required', 'string', new Lowercase],
]);
What do I need to do to be able to add my custom rule to the list above?
EDIT 1:
Per request I am showing the rule I have created. It is IDENTICALL to the one in the linked example in the documentation but I have switched the name of it from Uppercase to Lowercase and strtoupper to strtolower
public function passes($attribute, $value)
{
return strtolower($value) === $value;
}
You have a few options. One would be to use artisan to make a rule
php artisan make:rule Lowercase
You would end up with app\rules\Lowercase.php which you'd want to look something like this
<?php
namespace App\Rules;
use Auth;
use Illuminate\Contracts\Validation\Rule;
class Lowercase implements Rule
{
/**
* Create a new rule instance.
*
* #return void
*/
public function __construct()
{
}
/**
* Determine if the validation rule passes.
*
* #param string $attribute
* #param mixed $value
* #return bool
*/
public function passes($attribute, $value)
{
return strtolower($value) === $value;
}
/**
* Get the validation error message.
*
* #return string
*/
public function message()
{
return 'Must be lowercase!';
}
}
"Once the rule has been defined, you may attach it to a validator by passing an instance of the rule object with your other validation rules:"
So in your RegisterController
use App\Rules\Lowercase;
return Validator::make($data, [
'name' => ['required', 'string', 'max:255', new Lowercase],
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:6|confirmed',
]);
A second option would be to use a closure and not bother making the custom rule with artisan. This works well if you don't really need to use the rule somewhere else.
So in your RegisterController you can do something like this:
return Validator::make($data, [
'name' => [
'required',
'max:255',
function ($attribute, $value, $fail) {
if (strtolower($value) != $value) {
$fail($attribute.' must be all lowercase.');
}
},
],
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:6|confirmed',
]);
$request->validate([
'name' => ['required','string', 'max:255', 'new MyNewRuleClass(or Uppercase)'],
'email' => ['required', 'string','email','max:255','unique:users'],
'password' => ['required','string','min:6','confirmed'],
]);
Hope this helps you.

Laravel 5.5: Execute a method before registration

I'm using the default laravel authentication. Every user who registeres in my site needs a activation pin. The valid PINs are stored in a different table. Whenever a user registeres, I want to test if the PIN is valid or not. So, is there any method that I can override in RegisterController that executes before regstering the user?
Yes. You can override protected register method in RegisterController. This is a simple solution. I do this to validate params, save a new user, and force return JSON in one of my projects.
For example:
protected function register(Request $request)
{
$validator = Validator::make($request->all(), [
'first_name' => 'required',
'last_name' => 'required',
'email' => 'required|email|unique:users',
'phone' => 'required',
'pin' => 'required'
]);
//Check your PIN here, if it's wrong, append errors array
if ($validator->fails())
throw new ValidationFailed($validator->errors());
User::create([
'first_name' => $request->input('first_name'),
'last_name' => $request->input('last_name'),
'email' => $request->input('email'),
'phone' => $request->input('phone'),
'password' => bcrypt(str_random(10)),
'remember_token' => str_random(10),
]);
return ResponseJSON::make(trans('responses.registered'));
}
You can add a validation rule for validating the pin in the validator method like this :
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:6|confirmed',
'pin' => [
'required',
Rule::exists('pins')->where(function ($query) {
$query->where('Some condition');
}),
],
]);
}
I assume you have a table for pins called pins
extend the register function in user class:
public function register(Request $request)
{
event(new \App\Events\NewUserRegistered(Auth::user()));
return redirect($this->redirectPath());
}
NewUserRegistered:
namespace App\Events;
use App\Events\Event;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use App\User;
class NewUserRegistered extends Event
{
use SerializesModels;
public $userID;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct(User $userID)
{
//get whatever is massed in here's value in the id column
$this->id = $userID;
}
/**
* Get the channels the event should be broadcast on.
*
* #return array
*/
public function broadcastOn()
{
return [];
}
}

Categories