Validate time in relation to a checkbox is checked or not? - laravel

I have 3 input fields (reservationdate, starttime, endtime) and 1 checkbox (holeday).
If the checkbox clicked I do not need starttime and endtime. On the other hand starttime and endtime is required.
What can I do to solve this task?
I tried in Laravel the required_if validation-function. But I'm certainly using it wrong
// ReservationController store:
$data = $request->validate([
'userid' => 'required|numeric',
'vehicleid' => 'required|numeric',
'budgetid' => 'required|numeric',
'reservationdate' => 'required|date',
'starttime' => 'required_if:holeday,on|date_format:H:i|before_or_equal:endtime',
'endtime' => 'date_format:H:i',
'holeday' => 'boolean'
]);
index.blade.php (only the checkbox)
<div class="input-field col s2">
<label>
<input type="checkbox" name="holeday" class="filled-in" />
<span>Hole Day</span>
</label>
</div>
If the checkbox is checked I get the error-message "The starttime field is required when holeday is on." but in this case I need no error. Hey user it is OK. I don´t need a starttime or endtime. Your clicked the holeday.

Correct me if I am mistaken: you are trying to have starttime and endtime required only when holeday is not checked.
If I recall correctly when a checkbox is unchecked or disabled, it isn't sent at all to the server, so you can verify for the presence/absence of that field name:
// ReservationController store:
$data = $request->validate([
'userid' => 'required|numeric',
'vehicleid' => 'required|numeric',
'budgetid' => 'required|numeric',
'reservationdate' => 'required|date',
'starttime' => 'required_without:holeday|date_format:H:i|before_or_equal:endtime',
'endtime' => 'required_without:holeday|date_format:H:i',
'holeday' => 'required_without_all:starttime,endtime|in:on'
]);
Note: boolean validations accepts only true, 1``and "1" as thruthy values. But if the checkbox is set without a value attribute you would get "on" value as default check value.
However if you pass all of the three fields with their respective values, the validation would still pass, because required doesn't ensure that if the condition is not met that field must not be present.
You can take that into account and just write your logic to check if holeday has "on" value then ignore starttime and endtime values and viceversa.
Otherwise, you have to use a custom validation rule like this one (untested):
Validator::extend('not_present_with', function ($attribute, $value, $parameters, $validator) {
foreach ($parameters as $parameter) {
if (! Arr:has($validator->attributes(), $parameter)) {
return false;
}
}
return ! Arr::has($validator->attributes(), $attribute);
});
Then use the following validation rules:
// ReservationController store:
$data = $request->validate([
'userid' => 'required|numeric',
'vehicleid' => 'required|numeric',
'budgetid' => 'required|numeric',
'reservationdate' => 'required|date',
'starttime' => 'not_present_with:holeday|required_without:holeday|date_format:H:i|before_or_equal:endtime',
'endtime' => 'not_present_with:holeday|required_without:holeday|date_format:H:i',
'holeday' => 'not_present_with:starttime,endtime|required_without_all:starttime,endtime|in:on'
]);

Related

Laravel Controller Check Multiple Arrays

I am sending multiple arrays via AJAX to my controller and I'm having trouble with validation.
I have 2 text inputs. Now, the issue is that at times both these inputs are present, but at other times only one might be present.
<input type="text" name="typeDetails[games]" class="form-control input-global"/>
<input type="text" name="typeDetails[art]" class="form-control input-global"/>
My JS is like this.
var data = { 'typeDetails[games]' : [], 'typeDetails[art]' : [] };
$("input[name='typeDetails[games]']").each(function() {
data['typeDetails[games]'].push($(this).val());
});
$("input[name='typeDetails[art]']").each(function() {
data['typeDetails[art]'].push($(this).val());
});
In my controller, I want to (1) make sure that there's a validation of required and (2) if the "games" array is present, perform a particular action and if the "art" array is present, perform a different action.
$typeDetails = Input::get('typeDetails');
if ($request->has('typeDetails.games'))
{
return 'games';
}
if ($request->has('typeDetails.art'))
{
return 'art';
}
What happens here is that in my console it properly returns 'games', but even if the "art" array has values and is sent with the request, it doesn't return 'art'. I must be missing a fundamental understanding with php here.
Thanks!
ANSWER
Here's how I got it to work.
$typeDetails = Input::get('typeDetails');
$this->validate($request, [
'typeDetails.*.*' => 'required|max:50'
],[
'required' => 'You must type in some keywords to continue.',
'max' => 'Your input must be less than 50 characters.'
]);
if ($request->has('typeDetails.games'))
{
$gameInfo = Input::get('typeDetails.games');
foreach ($gameInfo as $key => $value)
{
DB::table('user_type')->insert([
'user_id' => Auth::user()->id,
'type_id' => '1',
'user_type_details' => $value,
'created_at' => Carbon::now()
]);
}
}
if ($request->has('typeDetails.art'))
{
$artInfo = Input::get('typeDetails.art');
foreach ($artInfo as $key => $value)
{
DB::table('user_type')->insert([
'user_id' => Auth::user()->id,
'type_id' => '2',
'user_type_details' => $value,
'created_at' => Carbon::now()
]);
}
}

Laravel 5 Validate Birthdate From Select Fields

I have a registration form with 3 select fields (month, day, year) which I want to grab, convert to proper date format, and validate. So, below are the 3 select boxes.
<div class="birthday_selects">
<select name="birthday_month">
....
</select>
<select name="birthday_day">
....
</select>
<select name="birthday_year">
....
</select>
</div>
I've read that I can use the following, but I get the error "...Http\Input not found..."
$birthday = Input::get('birthday_month')."-".Input::get('birthday_day')."-".Input::get('birthday_year')'
Okay, I can dd($birthday) and it comes out in the m-d-y as I've concatenated there. Now, I'm trying to validate that date against a prior date (to see if user is >13 years old). I'm using the following, but no luck.
public function postSignup(Request $request)
{
$birthdate = Input::get('birthday-month')."-".Input::get('birthday-day')."-".Input::get('birthday-year');
$this->validate($request, [
$birthdate => 'required',
]);
dd($birthdate);
}
When just having it be required, it doesn't work.
Your help is appreciated. Thanks!
It's not working because you're doing it wrong. What is wrong with it is the rule.
The rule key must be present in the form field's name.
For your answer, let's assume the $birthday will be 'jul-15-1992'. and you're going to put that variable inside the rule as a key. So, that's not valid because the field will never be present in the form field.
public function formPost(Request $request)
{
$rule = [
'birth_year' => 'required|numeric',
'birth_day' => 'required|numeric',
'birth_month' => 'required|numeric', // may be a string
];
$this->validate($request, $rule);
// check if the day is valid for the month manually.
// then form the DOB now.
}
Create Carbon date and add new [birth_day] input:
$all = $request->all();
$year = $all['birthday_year'];
$month = $all['birthday_month'];
$day = $all['birthday_day'];
// Create Carbon date
$date = Carbon::createFromFormat('Y-m-d', $year.'-'.$month.'-'.$day);
//add new [birth_day] input
$request->request->add(['birth_day' => $date->format('Y-m-d')]);
$validatedData = $request->validate([
'first_name' => 'required|string|max:255',
'last_name' => 'required|string|max:255',
'email' => 'required|string|email|max:255',
'password' => 'required|string',
'birth_day' => 'required|date_format:Y-m-d|before:today',// validate birth day
]);
Hope this will help you

Yii 2.0 Scenarios - Dynamic Validation

I have a situation where I would like to validate a textbox input; however, the type of validation is dependent on the selection of a dropdown list on that page (there would be multiple of each of these on a page). So, the textbox can take a string, an integer, a date, etc. and the user must select something from the dropdown list that would tell me what the data type has to be that the user will enter.
I was thinking to use scenarios for this; however, the textbox is 1 field in my model/database that accepts a string at the database level (I just don't want the user to enter a string when an integer is appropriate regardless of how I handle on the backend).
Here's what I was thinking so far, but I don't know if this is the best route to take for this problem? Also, if I can use the scenarios for this then how do I specify in the view the rules for the textbox when a user selects something that requires i.e..date input? Is there a way that I could call the rule with Ajax on click of dropdown list?? Sorry, this is probably a little too broad a question, but I'm new to Yii and I'm just trying to get headed down the right path with this. Thank you!
public function scenario()
{
return[
'isstring' => ['filter_value'],
'isint' => ['filter_value'],
'isdate' => ['filter_value'],
'isfloat' => ['filter_value'],
'all' => ['freq_int', 'freq_unit_fk', 'filter_field_fk', 'arithmetic_op', 'logic_op', 'filter_value']
];
}
public function rules()
{
return [
[['freq_int', 'freq_unit_fk'], 'integer', 'message' => 'Integer'],
[['freq_int', 'freq_unit_fk', 'filter_field_fk', 'arithmetic_op'], 'required'],
[['logic_op'], 'safe'],
[['filter_value'], 'integer', 'on' => 'isint'],
[['filter_value'], 'string', 'min' => '2', 'max' => '75', 'on' => 'isstring'],
[['filter_value'], 'trim', 'on' => 'isstring'],
[['filter_value'], 'number', 'on' => 'isfloat'],
[['filter_value'], 'date', 'on' => 'isdate']
];
}
Ok, so to give more detail, and I've decided to drop the idea of having the validation set based on a dropdown selection for now. Instead, it just needs to get set based on a value that I'm getting from the database when the page gets loaded. I have a partial view file called '_settings.php' and it gets rendered as a modal through a view file called 'manage.php'. Here is the code in _settings.php that displays the text boxes that I'm trying get the validation to work on:
foreach($crystalfields as $field)
{
if($field['custom'] == 4)
{
$datatype = $model->getDatatypeName($field['datatype']);
$filterstring = $form->field($model, 'filter_value', ['inputOptions' => ['id' =>'filterval'.$crystalid.'-'.$field['fieldid']]])
->textinput(['name' => 'filterval'.$crystalid.'-'.$field['fieldid']])
->label(false);
$filterstrings = $filterstrings.'<div class="form-group">
<div class="form_group row">
<label for="filterval'.$crystalid.'-'.$field['fieldid'].'" class="col-sm-3 control-label">'.$field['fieldname'].'</label>
<div class="col-sm-6 pull-right">'.$filterstring.'</div>
</div>
</div>';
}
...there is more to the foreach loop that is irrelevent. Basically, what I want to do is have the validation for this text box be set based on the result of the method $model->getDatatypeName($field['datatype']) ... method is part of my model where the validation rules exist; however, the primary key $field['datatype'] that I'm passing to this method is based on a query that is joining many related tables in my view model ..$model in this case. So when this method passes back 'string' I want to set the validation accordingly. There can be multiple of these text boxes within the modal that each have different validation types but are attached to the same 'filter_value' field each time.
I think the easier solution here would be to use the when-functionality. This gives you fine control over whether the rule should be triggered:
public function rules()
{
return [
[['freq_int', 'freq_unit_fk'], 'integer', 'message' => 'Integer'],
[['freq_int', 'freq_unit_fk', 'filter_field_fk', 'arithmetic_op'], 'required'],
[['logic_op'], 'safe'],
[['filter_value'], 'integer', 'when' => function ($model) {return $model->logic_op == 'integer'; }],
[['filter_value'], 'string', 'min' => '2', 'max' => '75', 'when' => function ($model) {return $model->logic_op == 'string'; }],
[['filter_value'], 'trim', 'when' => function ($model) {return $model->logic_op == 'string'; }]],
[['filter_value'], 'number', 'when' => function ($model) {return $model->logic_op == 'float'; }]],
[['filter_value'], 'date', 'when' => function ($model) {return $model->logic_op == 'date'; }]]
];
}

Laravel custom validation messages

I'm trying to validate a UK postcode using Laravel. Here's what I've got:
//routes.php
$rules = array(
'pcode' => array('required:|Regex:/^([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([A-Za-z][‌​0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z])))) [0-9][A-Za-z]{2})$/')
);
$messages = array(
'required' => 'The :attribute field is required.',
'pcode' => array('regex', 'Poscode should be a valid UK based entry'),
);
$validator = Validator::make(Input::all(), $rules, $messages);
In my blade:
<input id="postcode" name="pcode" value="{{Input::old('pcode')}}" type="text" placeholder="Postcode" class="form-control" xequired="" />
#if( $errors->has('pcode') ) <span class="error" style='background-color: pink;'>{{ $errors->first('pcode') }}</span> #endif
If I submit the form with an empty pcode field, it warns me for a required field. If I enter an invalid postcode, '74rht' say, my validator does nothing or fails to display my custom message as defined above?
The Laravel manual states:
Note: When using the regex pattern, it may be necessary to specify rules in an array instead of using pipe delimiters, especially if the regular expression contains a pipe character.
Change the $rules to this structure:
$rules = array(
'pcode' => array(
'required',
'Regex:/^([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([A-Za-z][‌​0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z])))) [0-9][A-Za-z]{2})$/'
)
);
If that doesn't work, then maybe your regex isn't valid, try to use a easier regex to check if the validator works.
Fist, you will want to register a custom validation rule with the validator.
Validator::extend('pcode_rule_name', function($attribute, $value)
{
return preg_match('/^([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([A-Za-z][‌​0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z])))) [0-9][A-Za-z]{2})$/', $value);
});
src: http://laravel.com/docs/validation#custom-validation-rules
Then you will want to specify custom messages in app/lang/en/validation.php
You will find a place to add your custom message for your your rule
'custom' => array(
'attribute-name' => array(
'rule-name' => 'custom-message',
),
),
You can add a rule like so:
'custom' => array(
'pcode' => array(
'pcode_rule_name' => 'Post Code should be a valid UK based entry',
),
),
There will also be an array to name your "pcode" field so it will be more eloquently named for rules like "required".
'attributes' => array(),
just add the name like so
'attributes' => array(
'pcode' => 'Postal Code",
),

CakePHP when using $model->save() validate rules and skip other rules

I'm using CakePHP 2.0 and I have a model that I use validation on it like this:
var $validate = array(
'title' => array(
'unique_rule'=>array(
'rule' => 'isUnique',
'on' => 'create',
'message' => 'This title has already been taken.'
),
'required_rule'=>array(
'required' => true,
'allowEmpty' => false,
'message' => 'The title field is required.'
)
)
);
, and in the controller I have an edit action and I use $model->save() to save date from $this->request->data, but it fails the isUnique validation rule, although it is not a new record insertion.
Is there any way to specify that it is an existing record, not a new one ?
If I got the question right you have to set the model's ID before calling $model->save(); so cakephp knows it's an update.
See http://book.cakephp.org/2.0/en/models/saving-your-data.html:
"Creating or updating is controlled by the model’s id field. If $Model->id is set, the record with this primary key is updated. Otherwise a new record is created:"
<?php
// Create: id isn't set or is null
$this->Recipe->create();
$this->Recipe->save($this->request->data);
// Update: id is set to a numerical value
$this->Recipe->id = 2;
$this->Recipe->save($this->request->data);
your validation array is wrong you haven't set a rule for 'required_rule' wich might trigger the isUnique error message.
var $validate = array(
'title' => array(
'unique_rule'=>array(
'rule' => 'isUnique',
'on' => 'create',
'message' => 'This title has already been taken.',
'last' => true
),
'required_rule'=>array(
'rule' => array('notEmpty'),
'message' => 'The title field is required.'
)
)
);
Also remember that using required=>true will NOT result check for actual data, it only wants the field to be present in the data-array and "" is also considered as present

Resources