I want to define a validation for my field in yii - validation

I want to define a validation for my field :
All numbers except zero and two
can I define my pattern?
what means $ and U ,p and other character?
'pattern'=>'/^[\p{L}\s,0-9]+$/u'

An overly complex regular expression won't do you any good. Instead, take advantage of the not setting, which is effectively inverting the pattern for you:
public function rules() {
return array(
array('field_name','pattern'=>'/^[02]$/','not'=>true),
);
}

In model add code
public function rules()
{
return array(
array('field_name','match', 'pattern'=>'/^[^02]+$/u','message'=>'Invalid Number.'),
);
}

you do it using your model rule
public function rules() {
return array(
// your other rules
array('fieldName', 'patternCheck'),
);
}
public function patterCheck($attribute, $params){
$pattern = '/^[\p{L}\s,0-9]+$/u';
preg_match($pattern, $attribute->fieldName, $matches, PREG_OFFSET_CAPTURE);
return $matches;
}
This will validate your field

Related

Opposite of required_if in laravel using multiple value evaluation

How to validate must null if another field has specific value or not null
In my case it is the opposite of required_if with multiple values
$rule = array(
'selection' => 'required',
'stext' => 'required_if:selection,2|required_if:selection,3',// stext should be null if selection is 2 or 3
);
And if needed how to perform own validation?
So in your example you can do something like this:
$rule = array(
'selection' => 'required',
'stext' => 'required'
);
// override the rule
if(in_array(request('selection'), [2, 3]))
{
$rule['stext'] = 'nullable';
}
This means if the selection is 2 the field will be required and if the selection field has any other value the stext field will be required.
I am not sure if I understood your question correctly. In any case the opposite of required_if is required_without so you can use that one if you want this field to be required even if the selection is empty.
With custom rule your passes method should look like this:
namespace App\Rules;
use Illuminate\Contracts\Validation\Rule;
class CustomRule implements Rule
{
protected $selection;
public __construct($selection)
{
$this->selection = $selection;
}
public function passes($attribute, $value)
{
return $value === null && in_array($this->selection, [2, 3]);
}
}
You use it like this:
$rule['stext'] = [ new CustomRule(request('selection') ]
I try to extend the validation rule. put the following in AppServiceProvider:
Validator::extend('null_if', function ($attribute, $value, $parameters, $validator) {
$other = $parameters[0];
$other_value = array_get(request()->toArray(), $other);
if ($parameters[1] == $other_value) {
return empty($value);
}
return true;
});
Tell me if it's work or what error given to you.

Retrieve parameters from custom validation object

I have basic custom validation rule. In
public function passes($attribute, $value)
{
foreach ($parameters as $key)
{
if ( ! empty(Input::get($key)) )
{
return false;
}
}
return true;
}
I have my rule defined. I, although need to retrieve parameters from the rule but the passes method does not provide it as an argument.
If I would use the style Validator:extends... that provides 4 arguments: $attribute, $value, $parameters, $validator. Then I could use the parameters easily, unfortunatelly I have to use this way.
EDIT:
To clear the question. I want to retrieve the parameters of the rule, like so in other way of coding it:
'not_empty:user_id'. The array of values behind the colon.
Edit:---
The custom rule object is simply an object. If you want to pass it any more parameters you can in it's constructor:
$request->validate([
'name' => ['required', new MyCustomRule('param', true, $foo)],
]);
Then save those and use them in your passes function.
public function __construct($myCustomParam){
$this->myCustomParam = $myCustomParam;
}
Then in your passes function use:
$this->myCustomParam
I believe the only way is to retrieve it from the request when using rule objects.
For example:
public function passes($attribute, $value)
{
foreach ($parameters as $key) {
// Or using \Request::input($key) if you want to use the facade
if (!empty(request()->input($key)) {
return false;
}
}
return true;
}

Laravel 5.5 / Validator / Custom rules

(edited to clearer purpose)
I discovered Laravel some months ago and I followed some Laracast videos. Now, I'm stuck with a problem of custom Validator.
I've got normal and permanent rules (date | required | min / max) to verify my form request. This part works.
But I've got a custom validation which could be verified as a normal rule IF one of the request parameter - select1 - is set to 1 (for exemple).
I read a dozen of explanation but nothing clear enough.
So, let start with my code. Thank you for your indulgence...
My question is into the customTest function on the bottom.
Thank you,
1/ I made a new Request with
php artisan make:controller priceRequest.php
2/ I made some rules and changed some lines.
public function authorize()
{
return true;
}
// Permanent RULES
public function rules()
{
$rules = [
'field1' => 'required|min:1|max:15',
'field2' => 'required',
'date1' => 'required|date',
'select1' => 'required',
];
return $rules;
}
Then I integrated a new function to perform a custom verification
public function withValidator($validator) {
$validator->after(function ($validator) {
if (!$this->customTests($this->request->get('data'))){
$validator->errors()->add('custom', 'Something is wrong');
}
});
}
Finally, I wrote the customTests function and it is inside this one I'm stuck !!
public function customTests($data) {
if ($data['select1'] == 1) {
// HERE MY QUESTION
// I'd like to verify that $data['date2']
// is a date and is set. So, I'd like to
// add a rule to rules (has I made with
// 'date1' => 'required|date',
// and return TRUE if the rule match or
// FALSE
}
}
So, I found the solution to my problem.
I made a mistake and a confusion because I tried to add the new rule into the ->after() function.
So, the correct code is the following :
public function withValidator($validator)
{
$validator->sometimes('ticket.price', 'required|integer|min:0.1', function ($input) {
if ($any_condition_who_need_to_verify_new_rule) {
return true;
}
else {
# Everything is perfect, this rule cas be omitted
}
$validator->after(function ($validator) use ($ticket) {
/* New test more complicated which cannot be
tested with a rule */
if ($this_test_is_complex_and_fails) {
$validator->errors()->add('validateTicket', 'This is another problem');
return false;
}
});
return $validator;
}

Yii2 custom validation rule not working

I'm trying to write some custom validation for a model in yii2, but I can't figure out why the validation always is positive, although my validation function always adds an error.
for example the rules
public function rules()
{
return [
...
[['myattribute'], 'myvalidation'],
];
}
public function myvalidation($attribute, $params)
{
$this->addError($attribute, "error");
}
the validate() function still returns true. What's the problem?
In validation rule add skipOnError => false
[
['myattribute', 'myvalidation', 'skipOnError' => false],
]
Then
$model->validate(); // should return false;
What I will recommend you is watch this lesson on custom roles and
read docs on it. It's not the best video tutorial, but this guy made it work correctly.
In your case :
1.In [['myattribute'], 'myvalidation'], remove extra array from here, make your model rules and custom valdation function look like this
public function rules()
{
return [
...
['myattribute', 'myvalidation'],
];
}
public function myvalidation($attribute, $params)
{
$this->addError($attribute, "error");
}
it's not wrong, but it's used when you have more than one attribute.
2.Then go to your form and put `` to your ActiveForm so it will look like this
<?php $form = ActiveForm::begin(['enableAjaxValidation' => true]); ?>
I mean, your need to do it in case if you want to validate it without reloading (using ajax).
3.Also add this to your controller's action that is connected to your view
if(Yii::$app->request->isAjax && $model->load($_POST)) {
Yii::$app->response->format = 'json';
return \yii\widgets\ActiveForm::validate($model);
}
This will validate your input in the form via ajax, if it's not ajax, this will not work.
['reg_date','validateDate', 'skipOnEmpty' => false, 'skipOnError' => false]
add this to your rules
public function validateDate($attribute,$params,$validator)
{
$validator->addError($this,$attribute,"Bugungi sana bo'lishi kerak!");
}
check this in your controller side like this
if($model->validate()){
echo "validate works";
}

Validation of array form fields in laravel 4 error

How can we validate form fields that are arrays? Take a look at the following code
UserPhone Model:
public static $rules= array(
'phonenumber'=>'required|numeric',
'isPrimary'=>'in:0,1'
)
...........
UserController:
$validation = UserPhone::validate(Input::only('phonenumber')));
if($validation->passes())
{
$allInputs = Input::only('phonenumber','tid');
$loopSize = sizeOf($allInputs);
for($i=0;$i<$loopSize;$i++)
{
$phone = UserPhone::find($allInputs['tid'][$i]);
$phone->phonenumber = $allInputs['phonenumber'][$i];
$phone->save();
}
return Redirect::to('myprofile')->with('message','Update OK');
}
else
{
return Redirect::to('editPhone')->withErrors($validation);
}
}
the $validation comes from a BaseModel which extends Eloquent.
In my view:
<?php $counter=1; ?>
#foreach($phones as $thephone)
<section class="col col-12">
<label class="label">Phone Number {{$counter++}}</label>
<label class="input">
<i class="icon-append icon-phone"></i>
{{Form::text('phonenumber[]',$thephone->phonenumber)}}
{{Form::hidden('tid[]',$thephone->id)}}
</label>
</section>
#endforeach
Everything is working fine and I get all the phone numbers I want in the Update Form, but I cannot update the model because the validation fails with the message "Phonenumber must be a number".
I know that there is not a simple solution for validating array form fields and I tried to extend the validator class but with no success.
How can I validate this kind of fields?
Here's the solution I use:
Usage
Simply transform your usual rules by prefixing each. For example:
'names' => 'required|array|each:exists,users,name'
Note that the each rule assumes your field is an array, so don't forget to use the array rule before as shown here.
Error Messages
Error messages will be automatically calculated by the singular form (using Laravel's str_singular() helper) of your field. In the previous example, the attribute is name.
Nested Arrays
This method works out of the box with nested arrays of any depth in dot notation. For example, this works:
'members.names' => 'required|array|each:exists,users,name'
Again, the attribute used for error messages here will be name.
Custom Rules
This method supports any of your custom rules out of the box.
Implementation
1. Extend the validator class
class ExtendedValidator extends Illuminate\Validation\Validator {
public function validateEach($attribute, $value, $parameters)
{
// Transform the each rule
// For example, `each:exists,users,name` becomes `exists:users,name`
$ruleName = array_shift($parameters);
$rule = $ruleName.(count($parameters) > 0 ? ':'.implode(',', $parameters) : '');
foreach ($value as $arrayKey => $arrayValue)
{
$this->validate($attribute.'.'.$arrayKey, $rule);
}
// Always return true, since the errors occur for individual elements.
return true;
}
protected function getAttribute($attribute)
{
// Get the second to last segment in singular form for arrays.
// For example, `group.names.0` becomes `name`.
if (str_contains($attribute, '.'))
{
$segments = explode('.', $attribute);
$attribute = str_singular($segments[count($segments) - 2]);
}
return parent::getAttribute($attribute);
}
}
2. Register your validator extension
Anywhere in your usual bootstrap locations, add the following code:
Validator::resolver(function($translator, $data, $rules, $messages)
{
return new ExtendedValidator($translator, $data, $rules, $messages);
});
And that's it! Enjoy!
Bonus: Size rules with arrays
As a comment pointed out, there's seems to be no easy way to validate array sizes. However, the Laravel documentation is lacking for size rules: it doesn't mention that it can count array elements. This means you're actually allowed to use size, min, max and between rules to count array elements.
It works best to extend the Validator class and re-use the existing Validator functions:
Validator::resolver(function($translator, $data, $rules, $messages)
{
return new Validation($translator, $data, $rules, $messages);
});
class Validation extends Illuminate\Validation\Validator {
/**
* Magically adds validation methods. Normally the Laravel Validation methods
* only support single values to be validated like 'numeric', 'alpha', etc.
* Here we copy those methods to work also for arrays, so we can validate
* if a value is OR an array contains only 'numeric', 'alpha', etc. values.
*
* $rules = array(
* 'row_id' => 'required|integerOrArray', // "row_id" must be an integer OR an array containing only integer values
* 'type' => 'inOrArray:foo,bar' // "type" must be 'foo' or 'bar' OR an array containing nothing but those values
* );
*
* #param string $method Name of the validation to perform e.g. 'numeric', 'alpha', etc.
* #param array $parameters Contains the value to be validated, as well as additional validation information e.g. min:?, max:?, etc.
*/
public function __call($method, $parameters)
{
// Convert method name to its non-array counterpart (e.g. validateNumericArray converts to validateNumeric)
if (substr($method, -7) === 'OrArray')
$method = substr($method, 0, -7);
// Call original method when we are dealing with a single value only, instead of an array
if (! is_array($parameters[1]))
return call_user_func_array(array($this, $method), $parameters);
$success = true;
foreach ($parameters[1] as $value) {
$parameters[1] = $value;
$success &= call_user_func_array(array($this, $method), $parameters);
}
return $success;
}
/**
* All ...OrArray validation functions can use their non-array error message counterparts
*
* #param mixed $attribute The value under validation
* #param string $rule Validation rule
*/
protected function getMessage($attribute, $rule)
{
if (substr($rule, -7) === 'OrArray')
$rule = substr($rule, 0, -7);
return parent::getMessage($attribute, $rule);
}
}
each()
It's not in the docs, but the 4.2 branch may have a simple solution around line 220.
Just like the sometimes($attribute, $rules, callable $callback) function, there is now an each($attribute, $rules) function.
To use it, the code would be something simpler than a sometimes() call:
$v->each('array_attribute',array('rule','anotherRule')); //$v is your validator
Caveats
sometimes() and each() don't seem to be easily chainable with each other so if you want to do specifically conditioned rules on array values, you're better off with the magic solutions in other answers for now.
each() only goes one level deep which isn't that different from other solutions. The nice thing about the magic solutions is that they will go 0 or 1 level deep as needed by calling the base rules as appropriate so I suppose if you wanted to go 1 to 2 levels deep, you could simply merge the two approaches by calling each() and passing it a magic rule from the other answers.
each() only takes one attribute, not an array of attributes as sometimes() does, but adding this feature to each() wouldn't be a massive change to the each() function - just loop through the $attribute and array_merge() $data and the array_get() result. Someone can make it a pull request on master if they see it as desirable and it hasn't already been done and we can see if it makes it into a future build.
Here's an update to the code of Ronald, because my custom rules wouldn't work with the array extension. Tested with Laravel 4.1, default rules, extended rules, …
public function __call($method, $parameters) {
$isArrayRule = FALSE;
if(substr($method, -5) === 'Array') {
$method = substr($method, 0, -5);
$isArrayRule = TRUE;
}
//
$rule = snake_case(substr($method, 8));
// Default or custom rule
if(!$isArrayRule) {
// And we have a default value (not an array)
if(!is_array($parameters[1])) {
// Try getting the custom validation rule
if(isset($this->extensions[$rule])) {
return $this->callExtension($rule, $parameters);
}
// None found
throw new \BadMethodCallException("Method [$method] does not exist.");
} // Array given for default rule; cannot be!
else return FALSE;
}
// Array rules
$success = TRUE;
foreach($parameters[1] as $value) {
$parameters[1] = $value;
// Default rule exists, use it
if(is_callable("parent::$method")) {
$success &= call_user_func_array(array($this, $method), $parameters);
} else {
// Try a custom rule
if(isset($this->extensions[$rule])) {
$success &= $this->callExtension($rule, $parameters);
}
// No custom rule found
throw new \BadMethodCallException("Method [$method] does not exist.");
}
}
// Did any of them (array rules) fail?
return $success;
}
There are now array validation rules in case this helps anybody. It doesn't appear that these have been written up in the docs yet.
https://github.com/laravel/laravel/commit/6a2ad475cfb21d12936cbbb544d8a136fc73be97

Resources