Solve laravel validation for field with relation - php

I have some problem where the validation is failing for my blade template with dropdown select on related table. I tried to searched for an answer but cannot found it.
To temporarily comment out the the field 'business_unit_id' inside the array in validate function to avoid the error.
In controller update function:
$item = CostCenter::findOrFail($id);
$validatedData = $request->validate([
'code' => 'bail|min:4|required|max:6',
'descr' => 'bail|min:4|required|max:50',
'business_unit_id' => 'required|integer',
]);
$item->fill($validatedData);
$item->business_unit_id = $request->businessUnit;
$item->save();
$request->session()->flash('status', 'Cost centers record was updated!');
return redirect()->route('costCenters.show', ['cost_centers' => $item->id]);
In blade template:
<label for="businessUnit" class="col-sm-2 col-form-label">Business Unit</label>
<select name="businessUnit" class="form-control">
#foreach (App\Models\BusinessUnit::all() as $data)
<option value="{{ $data->id }}"
{{ old('business_unit_id', $cost_centers->business_unit_id ?? '1')
!= $data->id ?: 'selected' }}>
{{ $data->code }} - {{ $data->descr }}
</option>
#endforeach
</select>
The notification received is "The business unit id field is required." with my error helper.

$validatedData = $request->validate([
'code' => 'bail|min:4|required|max:6',
'descr' => 'bail|min:4|required|max:50',
'businessUnit' => 'required|integer',
]);
Use businessUnit instead of business_unit_id
as we have to use the name of select tag...
don't use the id of options tag..

you can try this code...and use use keyword to of the code like use Validator;
$rules = [
'code' => 'bail|min:4|required|max:6',
'descr' => 'bail|min:4|required|max:50',
'businessUnit' => 'required|integer|exists:business_unit,id',
];
$message = [
'code.required' => 'code is required.',
'descr.required' => 'description field is required.',
'businessUnit.required' => 'The business unit id field is required.',
];
$validator = Validator::make($request->all(), $rules,$message);
if ($validator->fails()) {
$arr = array("status"=>400,"msg"=>$validator->errors()-
>first(),"result"=>array());
}
else
{
your code write in this section
}

For any request data validation in controller You can try like this:
$rule=array(
'code' => 'bail|min:4|required|max:6',
'descr' => 'bail|min:4|required|max:50',
'business_unit_id' => 'required|integer',
);
$validator= Validator::make($request->all(),$rule);

Related

How does this form gets the label name of each input

I'm working on some else project which is a Laravel 9 project and I have seen something interesting that have not seen it before.
Basically he defined the form inputs of projects like this (example):
<div class="form-group">
<span class="text-danger">*</span>
<label>{{ __('news')['nws_title'] }}</label>
<input type="text" name="nws_title" value="{{ old('nws_title' ,!empty($new) ? $new->nws_title : '') }}">
</div>
So as you can see for the <label>, this has been added:
{{ __('news')['nws_title'] }}
But I don't know what on earth is __('news') and what type of variable is this and how it calls the nws_title local name as label !!
So if you know, please let me know...
Also in the blade, he called the form request as well:
#php
$validationRequest = new \App\Http\Requests\News\NewsRequest();
$is_star = $validationRequest->rules();
#endphp
And this is the NewsRequest:
public function rules()
{
if($this->method() == 'POST') {
return [
'nws_title' => ['required'],
'nws_cat_id' => ['required'],
'nws_publish' => ['required', 'digits_between:0,1'],
'nws_lead' => ['required_if:nws_publish,1'],
'nws_description' => ['required_if:nws_publish,1'],
'nws_feature_image' => ['nullable', 'mimes:jpeg,jpg,png,bmp' ],
'nws_thumbnail_image' => ['nullable', 'mimes:jpeg,jpg,png,bmp', 'dimensions:min_width=200,min_height=200,ratio=1/1' ],
'gallery.*' => ['mimes:jpeg,jpg,png,bmp', 'nullable'],
];
}
return [
'nws_title' => ['required'],
'nws_cat_id' => ['required'],
'nws_publish' => ['required'],
'nws_lead' => ['required_if:nws_publish,1'],
'nws_description' => ['required_if:nws_publish,1'],
'nws_feature_image' => ['nullable', 'mimes:jpeg,jpg,png,bmp'],
'nws_thumbnail_image' => ['nullable', 'mimes:jpeg,jpg,png,bmp', 'dimensions:min_width=200,min_height=200,ratio=1/1'],
'gallery.*' => ['mimes:jpeg,jpg,png,bmp', 'nullable'],
];
}
Thanks in advance.
__() is a helper method for translation/localization. Depends on how localization is implemented in the app, but if it follows Laravel's default localization feature, then you can consult to the doc here.

Laravel backpack edit form displaying checklist items with selected values from database

In my crud controller, There is one field called "roles (Multiple checklist)", While before saving the roles, I am converting array into string like 1,2,3 using implode.
Ex: CrudController
setUp() method
$options = [
'name' => 'roles',
'label' => 'Roles',
'type' => 'checklist',
'entity' => 'roles',
'attribute' => 'name',
'model' => "Backpack\PermissionManager\app\Models\Role",
];
$this->crud->addField($options);
In Store method,
public function store(StoreRequest $request)
{
$sel_roles = $request->input("roles");
$roles = !empty($sel_roles) ? implode(",",$sel_roles) : "";
$request->request->set("roles",$roles);
//dd($request);
return parent::storeCrud($request);
}
Edit Method looks like this,
public function edit($id) {
$this->crud->hasAccessOrFail('update');
// get the info for that entry
$this->data['entry']= $this->crud->getEntry($id);
$options = [
'name' => 'roles',
'label' => 'Roles',
'type' => 'checklist',
'entity' => 'roles',
'attribute' => 'name',
'model' => "Backpack\PermissionManager\app\Models\Role",
];
$this->crud->addField($options);
$this->data['crud'] = $this->crud;
$this->data['fields'] = $this->crud->getUpdateFields($id);
$this->data['id'] = $id;
return view('crud::edit', $this->data);
}
If am trying to access, Edit page, I am getting below error,
ErrorException in line 15:
Call to a member function pluck() on string (View: /var/www/html/app/vendor/backpack/crud/src/resources/views/fields/checklist.blade.php)
checklist.blade.php page looks like below
<div #include('crud::inc.field_wrapper_attributes') >
<label>{!! $field['label'] !!}</label>
<?php $entity_model = $crud->getModel(); ?>
<div class="row">
#foreach ($field['model']::all() as $connected_entity_entry)
<div class="col-sm-4">
<div class="checkbox">
<label>
<input type="checkbox"
name="{{ $field['name'] }}[]"
value="{{ $connected_entity_entry->id }}"
#if( ( old( $field["name"] ) && in_array($connected_entity_entry->id, old( $field["name"])) ) || (isset($field['value']) && in_array($connected_entity_entry->id, $field['value']->pluck('id', 'id')->toArray())))
checked = "checked"
#endif > {!! $connected_entity_entry->{$field['attribute']} !!}
</label>
</div>
</div>
#endforeach
</div>
{{-- HINT --}}
#if (isset($field['hint']))
<p class="help-block">{!! $field['hint'] !!}</p>
#endif
</div>
How do I display the roles with selected values in the edit page.
Thanks
After hours of debug and verified,
Send the edit values in the collection format,
$options = [
'name' => 'role_id',
'label' => 'Roles',
'type' => 'checklist',
'entity' => 'roles',
'attribute' => 'name',
'model' => "Backpack\PermissionManager\app\Models\Role",
"value" => collect([$edit_value_array])
];

Laravel how to add records with create function in controller?

NewsController.php
This is the contoller and i use the create function to add record to the database but when i add all records will be empty
public function insertNews() {
$attribute = [
'Ntitle' => 'News Title',
'Ndesc' => 'News Description',
'Naddedby' => 'News Added By',
'Ncontent' => 'News Content',
'Nstatus' => 'News Status'
];
$data = $this->validate(request(), [
'Ntitle' => 'required',
'Ndesc' => 'required',
'Naddedby' => 'required',
'Ncontent' => 'required',
'Nstatus' => 'required'
], [], $attribute);
News::create($data);
return redirect('all/news');
}
and i use dd() to show the record and it will show with the token and all other values
dd(request()->all())
News.php
and this is the model file
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class News extends Model
{
use SoftDeletes;
protected $primaryKey = 'News_ID';
protected $date = ['delete_at'];
protected $fillable = ['News_Title', 'News_Descrption', 'News_Content', 'Added_By', 'News_Status'];
}
web.php
this is the web file (routes)
Route::post('insert/news', 'NewsController#insertNews');
news.blade.php
and this is the blade file that contain the form that i sent to the controller
<form action="{{ url('insert/news') }}" method="POST">
{{ csrf_field() }}
<input type="text" name="Ntitle" value="{{ old('Ntitle') }}" placeholder="News Title"><br />
<input type="text" name="Ndesc" value="{{ old('Ndesc') }}" placeholder="News Descrption"><br />
<input type="number" name="Naddedby" value="{{ old('Naddedby') }}" placeholder="News Added By"><br />
<textarea name="Ncontent" value="{{ old('Ncontent') }}" placeholder="News Content"></textarea><br />
<select name="Nstatus">
<option value="Active" {{ old('Nstatus') == 'Active' ? 'selected' : '' }}>Active</option>
<option value="Pending" {{ old('Nstatus') == 'Pending' ? 'selected' : '' }}>Pending</option>
<option value="Disabled" {{ old('Nstatus') == 'Disabled' ? 'selected' : '' }}>Disabled</option>
</select><br />
<input type="submit" value="Add News">
</form>
enter image description here
There are number of reasons for your code to not work:
In your case, you have incorrectly equated the $data to the validation object. You should use the $attribute (the key value array of data, not the validation object) in the create function instead of the $data.
Secondly the keys passed in the array of the create data should be exactly same to the fields name of the table that you are using for data insertion. I see that your code shows Ntitle, Ndesc etc being used for the validation and in the $attribute array, while the fillable protected $fillable has the different field names! So, please use the correct field names in the data that you are passing and in the $fillable in the model. I am writing the below code assuming that Ntitle, Ndesc, Naddedby, Ncontent, Nstatus are the field names of your table. As per that please refer to the below code!
public function insertNews() {
$attribute = [
'Ntitle' => 'News Title',
'Ndesc' => 'News Description',
'Naddedby' => 'News Added By',
'Ncontent' => 'News Content',
'Nstatus' => 'News Status'
];
$this->validate(request(), [
'Ntitle' => 'required',
'Ndesc' => 'required',
'Naddedby' => 'required',
'Ncontent' => 'required',
'Nstatus' => 'required'
], [], $attribute);
News::create($attribute);
return redirect('all/news');
}
Make sure that you have all the fields added to protected $fillable = []; in your model like this:
class News extends Model {
protected $fillable = [
'Ntitle', 'Ndesc', 'Naddedby', 'Ncontent', 'Nstatus'
];
You need to pass the value to the create() method.
//Passing the request to create method
News::create($request->all());
return redirect('all/news');
It will now store if you have added inputs name in the $fillable variable in the News model.
//News.php (Model)
protected $fillable = ['Ntitle', 'Ndesc', 'Naddedby', 'Ncontent', 'Nstatus'];
I prefer to use
//News.php (Model)
protected $guarded = [];
Can i have your web route?
so i can tell that what's the mistake,
i think your route should be
Route::namespace('your_Controller_Foldername')->group(function () {
Route::resource('insert/news', 'NewsController');
});

How to validate the field "questionOptions[]"? (it should be required, it should not be null)

I have a page for the user to create a question. For that, the user needs to introduce a title for the question and the type. To select the type there is a select menu:
<div class="form-group">
<label for="type">Field type</label>
<select class="form-control" name="type" id="customQuestionType">
<option value="text">Text</option>
<option value="long_text">Long Text</option>
<option value="checkbox">Checkbox</option>
<option value="radio_btn">Radio button</option>
<option value="select_menu">Select menu</option>
<option value="file">FIle</option>
</select>
</div>
If the user selects the type select menu, checkbox or radio button he also needs to introduce the options for the field. So if the user selects a field type of select menu, checkbox or radio button it will appear 2 fields by default for the user to introduce the values for the options:
<div class="form-group" id="availableOptions">
<label for="inputName">Available Options</label>
<div class="option">
<input type="text" class="form-control col-md-8" name="questionOptions[]">
<input type="button" class="removeOption btn btn-outline-primary col-md-3" value="Remove option"/>
</div>
<div class="option mt-3 d-flex justify-content-between">
<input type="text" class="form-control col-md-8" name="questionOptions[]">
<input type="button" class="removeOption btn btn-outline-primary col-md-3" value="Remove Option"/>
</div>
</div>
Doubt: My doubt is about how to validate the questionOptions form fields, because if the user select checkbox, select menu or radio button the user should at least introduce the value for 1 option input, that is the options cannot be null/empty. So in the rules I have " 'questionOptions' => 'required'". But if the user dont introduce any value for any option it appears an error instead of the validation message:
SQLSTATE[23000]: Integrity constraint violation:
1048 Column 'value' cannot be null
(SQL: insert into `question_options`
(`question_id`, `value`, `updated_at`,
`created_at`) values (8, , 2018-08-15 23:14:08, 2018-08-15 23:14:08)).
Do you know where is the issue?
Method to store the question:
public function store(Request $request, $id)
{
$rules = [
'question' => 'required',
'type' => 'required|in:text,long_text,select_menu,radio_btn,file,checkbox',
'questionOptions' => 'required'
];
$customMessages = [
'question.required' => 'The field title is required.',
'type.required' => 'The field type is required.',
'type.in' => 'Please introduce a valid type.',
'questionOptions.required' => 'Please introduce the value at least for 1 option.',
];
$this->validate($request, $rules, $customMessages);
$congress= Congress::find($id);
$question = Question::create([
'congress_id' => $congress->id,
'question' => $request->question,
'type' => $request->type,
]);
if (in_array($request->type, Question::$typeHasOptions)) {
foreach ($request->input('questionOptions') as $questionOption) {
QuestionOption::create([
'question_id' => $question->id,
'value' => $questionOption
]);
}
}
Session::flash('success', 'Question created with success.');
return redirect()->back();
}
You could try to custom rule. like this..
write custom rule in provider
public function boot()
{
Validator::extend('check_empty', function ($attribute, $value, $parameters, $validator) {
//your code to check if the value is empty in your way condition
return check_array_empty_your_code($value)
});
//this is for custom message
Validator::replacer('dns_email', function ($message, $attribute, $rule, $parameters) {
return "Please introduce the value at least for 1 option.";
});
}
then make request class
class StoreRequest extends FormRequest
{
public function authorize()
{
return true;
}
public function rules()
{
return [
'question' => 'required',
'type' => 'required|in:text,long_text,select_menu,radio_btn,file,checkbox',
'questionOptions' => 'required|check_empty'
]
}
public function messages()
{
return [
'question.required' => 'The field title is required.',
'type.required' => 'The field type is required.',
'type.in' => 'Please introduce a valid type.',
'questionOptions.required' => 'Value is required',
];
}
}
Then use the request class in controller
public function store(StoreRequest $request, $id)
{
$congress= Congress::find($id);
$question = Question::create([
'congress_id' => $congress->id,
'question' => $request->question,
'type' => $request->type,
]);
if (in_array($request->type, Question::$typeHasOptions)) {
if (isset($request->questionOptions)) {
foreach ($request->questionOptions as $questionOption) {
QuestionOption::create([
'question_id' => $question->id,
'value' => $questionOption
]);
}
} else {
//return error
}
}
Session::flash('success', 'Question created with success.');
return redirect()->back();
}
To validate form fields expecting an array as value like is the case of questionOptions[], you can follow this approach in your validation rules and custom messages:
$rules = [
'question' => 'required',
'type' => 'required|in:text,long_text,select_menu,radio_btn,file,checkbox',
'questionOptions' => 'required|array',
'questionOptions.*' => 'filled'
];
$customMessages = [
'question.required' => 'The field title is required.',
'type.required' => 'The field type is required.',
'type.in' => 'Please introduce a valid type.',
'questionOptions.required' => 'Please introduce the value at least for 1 option.',
'questionOptions.array' => 'Please introduce the value at least for 1 option.',
'questionOptions.*.filled' => 'Please introduce the value at least for 1 option.'
];

Laravel "At Least One" Field Required Validation

So I have this form with these fields
{{ Form::open(array('url' => 'user', 'id' => 'user_create_form')) }}
<div class="form-input-element">
<label for="facebook_id">ID Facebook</label>
{{ Form::text('facebook_id', Input::old('facebook_id'), array('placeholder' => 'ID Facebook')) }}
</div>
<div class="form-input-element">
<label for="twitter_id">ID Twitter</label>
{{ Form::text('twitter_id', Input::old('twitter_id'), array('placeholder' => 'ID Twitter')) }}
</div>
<div class="form-input-element">
<label for="instagram_id">ID Instagram</label>
{{ Form::text('instagram_id', Input::old('instagram_id'), array('placeholder' => 'ID Instagram')) }}
</div>
{{ Form::close() }}
I'd like to tell Laravel that at least one of these fields is required. How do I do that using the Validator?
$rules = array(
'facebook_id' => 'required',
'twitter_id' => 'required',
'instagram_id' => 'required',
);
$validator = Validator::make(Input::all(), $rules);
Try checking out required_without_all:foo,bar,..., it looks like that should do it for you. To quote their documentation:
The field under validation must be present only when the all of the other specified fields are not present.
Example:
$rules = array(
'facebook_id' => 'required_without_all:twitter_id,instagram_id',
'twitter_id' => 'required_without_all:facebook_id,instagram_id',
'instagram_id' => 'required_without_all:facebook_id,twitter_id',
);
$validator = Validator::make(Input::all(), $rules);
**For automatic validation**
$rules = array(
'facebook_id' => 'required_without_all:twitter_id,instagram_id',
'twitter_id' => 'required_without_all:facebook_id,instagram_id',
'instagram_id' => 'required_without_all:facebook_id,twitter_id',
);
$message = array(
'facebook_id' => 'The facebook field is required when none of twitter / instagram are present.',
'twitter_id' => 'The twitter field is required when none of facebook / instagram are present.',
'instagram_id' => 'The instagram field is required when none of twitter / facebook are present.');
$validator = Validator::make(Input::all(), $rules, $message)->validate();
use this code i already made it
php artisan make:rule RequiredWithout
use Illuminate\Contracts\Validation\Rule;
class RequiredWithout implements Rule
{
private $without = [];
private $current_attribute = "";
private $no_need = "";
public function __construct($without)
{
if(is_string($without))
{
$this->without = [$without];
}
elseif(is_array($without))
{
$this->without = $without;
}
else
throw new \Exception('$without must be array or string');
}
public function passes($attribute, $value)
{
$this->current_attribute = $attribute;
$requests = request()->all();
foreach ($this->without as $WO_i)
{
if(array_key_exists($WO_i, $requests))
{
$this->no_need = $WO_i;
return false;
}
}
return true;
}
public function message()
{
return "the $this->current_attribute Field and $this->no_need Shouldn't be Exist in this request together";
}
}
and then in the controller use this
'country_id' => ['nullable', 'exists:countries,id', new ValidCountryID(), new RequiredWithout('country_code')],
'country_code' => ['nullable', 'exists:countries,IsoCountryCode', new ValidCountryID(), new RequiredWithout('country_id')],
Rule required_without_all can be hacked to get the desired results.
Create a dummy rule for require_one, and pass all fields to the rule params. if none exists, the dummy rules fires up with required.
$rules = array(
'facebook_id' => 'required',
'twitter_id' => 'required',
'instagram_id' => 'required',
);
$keys = implode(',', array_keys($rules));
$rules['require_one'] = "required_without_all:$keys";
$messages = [
'require_one.required_without_all' => '*At least one field is required'
];
$validator = Validator::make(Input::all(), $rules, $messages);
This is possible to implement with an After Validation Hook:
$validator->after(function ($validator) {
if (empty($this->validated())) {
$validator->errors()->add('empty', 'At least one field must be provided.');
}
});
Or if you are using a FormRequest:
public function withValidator($validator)
{
$validator->after(function ($validator) {
if (empty($this->validated())) {
$validator->errors()->add('empty', 'At least one field must be provided.');
}
});
}

Categories