Laravel Version: 5.7
I want to set a validation. when checkbox is checked, then set a 'between' rule.
just like below.
required|integer|between:1,2
but when checkbox is not checked is not need between rule like below
required|integer
I try to use validation, But I don't know how to set.
Inputs
<input type="checkbox" name="checkbox">
<input type="number" name="number">
I don't know if you are using form request or not, so here is a solution for validation using a Form request
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class DepartmentRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
public function rules()
{
rules = [];
if ($this->attributes->has('checkbox')) {
$rules['key'] = 'required|integer|between:1,2',
} else {
$rules['key'] = 'required|integer',
}
// Your other validation rules here
return $rules;
}
public function messages()
{
return [
// Your custom validation messages here
];
}
}
Remember: You must change the key with the field name you want to validate.
Hope it helps.
Related
I am using laravel 5.8 version, i have one api which is responsible for registering ,i create one Request file which contains rules() and messages() function to display error messages but it's not throwing any error messages if any validation fails ,why this is happening can somebody explain ?
UserController.php
<?php
namespace App\Http\Controllers;
use App\Http\Requests\userRequest;
use App\UserSection;
class UserController extends Controller
{
public function userRegister(userRequest $request){
//logic of my code
return response()->json($success);
}
}
userRequest.php
<?php
namespace App\Http\Requests;
use App\Rules\CustomRule;
use Illuminate\Foundation\Http\FormRequest;
class userRequest extends FormRequest
{
public function messages()
{
return [
'first_name.required' => 'A title is required',
];
}
/**
* 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 [
'first_name' => 'string|required|max:25',
'phone_number' => 'required|integer'
];
}
}
The error i am facing when i hit the route without first_name key it's showing 404 not found error
you might have missed headers part for taking the form-data
Accept = application/json
As laravel docs
If validation fails, a redirect response will be generated to send the
user back to their previous location. The errors will also be flashed
to the session so they are available for display. If the request was
an AJAX request, a HTTP response with a 422 status code will be
returned to the user including a JSON representation of the validation
errors.
So you need to specify the response type you expect, if you use postman for testing your api end point you have to add in request header Accept:application/json
<?php
namespace App\Http\Controllers;
use App\Http\Requests\userRequest;
use App\UserSection;
class UserController extends Controller
{
public function userRegister(userRequest $request){
//logic of my code
return response()->json($success);
}
}
Validation functions don't work.
Validation customs rules are not applied to the usernmane field
module dektrium/user
PHP 7.1
Yii 2.0.16
Already try all from here: https://www.yiiframework.com/doc/guide/2.0/en/input-validation (Inline Validators and Standalone Validators)
Model Agent :
class Agent extends Profile
{
public $username;
public $password;
public $password2;
public function rules()
{
$rules = [
['username', AgentValidator::className()],// it's not work
[['email'], 'email'], // it's work
['password2', 'compare', 'compareAttribute' => 'password', 'message' => 'Пароли должны совпадать'],//// it's work
];
return array_merge(parent::rules(), $rules);
}
}
AgentValidator.php
<?php
namespace app\components;
use yii\validators\Validator;
class AgentValidator extends Validator
{
public function validateAttribute($model, $attribute)
{
if (User::findOne(['username' => $this->$attribute]]) {
$this->addError($attribute, 'Такой логин уже занят');
}
}
}
You are using standalone validator and you want the frontend validation to be working along with the backend so you need to override the yii\validators\Validator::clientValidateAttribute() in your Standalone validator AgentValidator, which returns a piece of JavaScript code that performs the validation on the client-side.
Within the JavaScript code, you may use the following predefined variables:
attribute: the name of the attribute being validated.
value: the value being validated.
messages: an array used to hold the validation error messages for the attribute.
deferred: an array which deferred objects can be pushed into.
You can go through the section Implementing Client Validation to read in detail.
Apart from everything listed above you have a mistake in your validator code User::findOne(['username' => $this->$attribute]], you need to use $model->$attribute rather than $this->$attribute which will never get the exact value entered in the form. You might have mistakenly added it from the model.
Your current validator should be like below
<?php
namespace app\components;
use yii\validators\Validator;
class AgentValidator extends Validator
{
public $message='Такой логин уже занят';
public function validateAttribute($model, $attribute)
{
if (User::findOne(['username' => $model->$attribute])!==null)
{
$model->addError($attribute, $this->message);
}
}
public function clientValidateAttribute($model, $attribute, $view) {
//check if user exists
$userExists = User::findOne(['username' => $model->$attribute])!==null;
$message = json_encode($this->message, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
return <<<JS
if($userExists){
messages.push($message);
return;
}
JS;
}
}
So, Thank Muhammad Omer Aslam for right answer.
Yii2 does't generate any js code for validation by custom rules. Therefore it is necessary to add a check to the controller and the form
For me it:
Controller
if (\Yii::$app->request->isAjax) {
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
$model->load(\Yii::$app->request->post());
return \yii\widgets\ActiveForm::validate($model);
}
Form
$form = ActiveForm::begin([ 'enableAjaxValidation' => true]);
I have 2 fields for postal code main and sub.
<input type="text" name="postal01">
<input type="text" name="postal02">
I would like to have validation for numeric and size of both fields added.
What I want to do is showing validation error for one field as postal_cd, not each field error.
I had tried in a request class extended FormRequest.
class MemberRequest extends FormRequest
{
public function all($keys = null)
{
$result = parent::all($keys);
if($this->filled('postal01') && $this->filled('postal02')) {
$results['postal_code'] = $this->input('postal01') . $this->input('postal02');
}
return $result;
}
However it did not work like I expected.
How can I handle this case?
You can use an After Validation Hook. Add the following to your Form Request:
/**
* Configure the validator instance.
*
* #param \Illuminate\Validation\Validator $validator
* #return void
*/
public function withValidator($validator)
{
$validator->after(function ($validator) {
if($validator->errors()->has('postal01') || $validator->errors()->has('postal02')) {
$validator->errors()->add('postal_cd', 'Please enter a postal code');
}
});
}
... and then to display it on your blade:
{{ $errors->first('postal_cd') }}
That was my typo.
class MemberRequest extends FormRequest
{
public function all($keys = null)
{
$result = parent::all($keys);
if($this->filled('postal01') && $this->filled('postal02')) {
$result['postal_code'] = $this->input('postal01') . $this->input('postal02');
// $results['postal_code'] = $this->input('postal01') . $this->input('postal02');
}
return $result;
}
Returned value should have been $result. But it was typo $results['postal_code'].
It works.
Is it possible to sanitize certain inputs on (or before validation)?
I have this rules for now (as example):
public function rules()
{
return [
'name' => 'required|min:3|max:255|string',
'description' => 'string',
'hours.*' => ['required', new Hours],
];
}
I want to sanitize name and description, but I don't to sanitize hours. Is this possible to do on validation, or I have to sanitize after validation and before insert?
I don't recommend to do sanitization after validation.
Suppose we have a blog system and guests/users can comment on posts, and the minimum characters in a comment is 10
If someone comments with thank you (there's a trailing space), it will be passed at the validation level because it's a 10 chars comment, but when we sanitize the comment, say we trim it, it will be left with 9 chars. This is a silly example but can be something very important in your business logic somewhere.
Sanitize then validate.
To do request inputs sanitization, this article has a good pattern to do it https://medium.com/#melihovv/how-to-sanitize-input-data-in-declarative-manner-in-laravel-e4486068f751
To cannot do this before validation as the original value will still be there in request. It can be easily dealt with mutators.
You can use Eloquent's Mutators to format attribute values in Eloquent Model before insert or update.
To define mutator, add set prefix and attribute suffix with the attribute's name. Like following
// Name mutator
public function setNameAttribute($name)
{
$this->attributes['name'] = strtolower($name); // used strtolower just to show the mutation
}
// Description mutator
public function setDescriptinAttribute($description)
{
$this->attributes['description'] = strtolower($description); // used strtolower just to show the mutation
}
Check documentation for more info https://laravel.com/docs/5.6/eloquent-mutators#defining-a-mutator
The only way I could think of validating the input like that would be validating it on the client side. So basically using Javascript to validate it. If the user for some reason disables Javascript your server site validation would work. What you could try as well would be to post the data asynchronous using Ajax for instance and immidietly return an error message if the validation fails, this approach would be server side.
test this :
web.php
Route::get('test/', 'TestController#test');
TestController class :
<?php
namespace App\Http\Controllers;
use App\Http\Requests\PostRequest;
use App\Post;
class PostController extends Controller
{
public function test(PostRequest $request)
{
dd($request->get('name'));
}
}
PostRequest class :
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class PostRequest 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()
{
$this->sanitize();
return [
'name'=>'required',
'description'=>'required',
'description'=>'required',
];
}
public function sanitize()
{
$input = $this->all();
$input['name'] = $input['name'].'some change';
$input['description'] = $input['description'].'another change';
$this->replace($input);
}
}
As you can see, I defined a method called sanitize in PostRequest
Now when I set the value of the name to the ali in URL, but the ali some change value will be printed.
You can also use the daylerees / sanitizer package.
there is a UpdateUserRequest form request that verify fields value against its rules defined in rules mathod .it has rules() and authorize() methods by default. i want prevent verifying and updating empty fields (such as password) .
using sometimes in rules is not useful as html inputs will be present in POST request even if they are empty.
array:6 [▼
"_method" => "PATCH"
"_token" => "Cz79rRez2f6MG0tTU17nVwXD0X1lNGH1hA7OORjm"
"name" => "john"
"email" => "mymail#gmail.com"
"password" => ""
"password_confirmation" => ""
]
so i should remove empty keys of POST request before using sometimes in rules.
the question is : Where is the best place to purge Request array?
is there any laravel build in method to manage such situations?
P.S :Solution:
#Bogdon solution is still valid and works, but there is another simple ,nice ,neat solution adopted from here:
just override all() method inside form request
class RegistrationRequest extends Request
{
...
public function all()
{
$attributes = parent::all();
if(isset($attributes['password']) && empty($attributes['password']))
{
unset($attributes['password']);
}
$this->replace($attributes);
return parent::all();
}
...
}
To make this work you'll need to modify the contents of the App\Http\Requests\Request class to allow a way to sanitize the input (class code taken from this Laracasts post):
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
abstract class Request extends FormRequest
{
/**
* Validate the input.
*
* #param \Illuminate\Validation\Factory $factory
* #return \Illuminate\Validation\Validator
*/
public function validator($factory)
{
return $factory->make(
$this->sanitizeInput(), $this->container->call([$this, 'rules']), $this->messages()
);
}
/**
* Sanitize the input.
*
* #return array
*/
protected function sanitizeInput()
{
if (method_exists($this, 'sanitize'))
{
return $this->container->call([$this, 'sanitize']);
}
return $this->all();
}
}
After that you just need to write add sanitize method in the UpdateUserRequest class that removes the password field from the input when it's empty:
public function sanitize()
{
if (empty($this->get('password'))) {
// Get all input
$input = $this->all();
// Remove the password field
unset($input['password']);
// Replace the input with the modified one
$this->replace($input);
}
return $this->all();
}
Now using the sometimes rule for the password field will work:
public function rules()
{
return [
// Other rules go here
'password' => 'sometimes|required|confirmed'
];
}
I'm not sure about the best way to purge the fields, but this is how I currently handle user updates on my system.
I find the user based on the $id passed through and then update the appropriate records. I assume that name and email will never be empty, it is only the password that can be empty - and so we can just set the name and email fields to the values passed in and then use an if statement to check if the password field is empty or not and update accordingly.
Something along the lines of this is what I use:
public function update($id)
{
$user = User::find($id);
$user->name = Input::get('name');
$user->email = Input::get('email');
if (Input::get('password') != "")
{
$user->password = Hash::make(Input::get('password'));
}
$user->save();
}