Laravel custom validation message for multiple fields with the same name - laravel

I have the following validation in the controller's action:
foreach ($request['qtys'] as $key => $val){
if (!$this->_validateMinQty($key, $job, $val)){
$customerTitle = $job->customers()->where('customer_id',$key)->first()->title;
return redirect()->back()->withErrors(['qtys' => __('The qty of the customer :customerTitle is less than allowed qty',['customerTitle' => $customerTitle])]);
}
}
This check multiple form's input named qtys in the view:
#foreach($job->customers as $customer)
<div class="form-group {{$errors->first('qtys has-error')}}">
{!! Form::label('qtys-'.$customer->id, __('Qty').' '.$customer->title) !!}
<div class="row">
<div class="col-md-9">
{!! Form::text('qtys['.$customer->id.']',$customer->pivot->e_production,['class' =>'form-control qtys', "data-sumequal"=>"qty",'required' => 'required','title' => $customer->pivot->aid,'id' => 'qtys-'.$customer->id]) !!}
<div class="help-block with-errors"></div>
#php ($eleE = $errors->first('qtys'))
#include('layouts.form-ele-error')
</div>
<div class="col-md-3">
<i class="fox-add"></i>{{__('Add Storage')}}
</div>
</div>
</div>
#endforeach
The above code works, but with the following limitation:
The error message is rendered under every input named qtys[x] where x is an integer and the first input only Testana has the invalid qty, like the following screen shot:
In the controller's action return message, I have tried to use indexed name for the input like the following:
return redirect()->back()->withErrors(['qtys.10' => ....
However, it prevents rendering the error message under any qtys field. Is there any solution?

The solution that I have found starts from the definition of first method found in the view :
#php ($eleE = $errors->first('qtys'))
This, in my code, should be changed to:
#php ($eleE = $errors->first('qtys.'.$customer->id))
Because the multiple fields have gotten keys equals to the customer id. This is a technique I usually use, when I want to send double piece of data in single post or in single form element.
Then in the controller, I keep the first try,
return redirect()->back()->withErrors(['qtys.'.$key => __('The qty of the customer :customerTitle is less than allowed qty',['customerTitle' => $customerTitle])]);
Where $key is an integer.

Related

Save array [ ] of form data in same columns individual row - Laravel

when the user click add more and submit their form data, I'm having a problem saving form array like this (service[], Amount[], Description[]) in database rows. I have two related tables of invoices and invoice_details, i want the form array to submit the list of form data into the invoice_details table. I have successfully created the models and relations between the invoice and invoice_details.
<!--Blade -->
<div class="service-box">
<div class="row">
<div class="col-md-12 service-group">
<div class="row">
<div class="form-group mb-3 col-md-6">
<label class="form-label">Service</label>
<div >
<select type="text" class="form-select" placeholder="Services" value="" name="service[]" id="service">
<option value="" disabled selected>Select your option</option>
#foreach ($services as $service)
<option value="{{$service->service_name}}" data-id="{{$service->amount}}">{{$service->service_name}}</option>
#endforeach
</select>
</div>
</div>
<div class="form-group mb-3 col-md-6">
<label class="form-label">Amount</label>
<div >
<input type="text" class="form-control" name="amount[]" id="amount" placeholder="Amount" readonly>
</div>
</div>
<div class="form-group mb-3 col-md-12">
<label class="form-label">Description</label>
<textarea class="form-control" id="description" name="description[]" rows="6" placeholder="Description.." ></textarea>
</div>
</div>
</div>
</div>
</div>
//Controller
$invoicedetailModel = new Invoice_detail;
//Here is where the problem lies, I have to save for arrays.
$invoicedetailModel->service = request('service');
$invoicedetailModel->amount = request('amount');
$invoicedetailModel->description = request('description');
$invoiceModel->Invoice_details()->save($invoicedetailModel);
It seems to me (correct me if I'm misinterpreting) that you're trying to save a batch of different InvoiceDetails and attach them to an original Invoice model.
The problem here is that you're trying to do so by passing arrays to a single invoiceDetails model so let's suppose you have the you have two detail instances passed by form you would have the request parameters structured like this:
$request->service: ['serviceX','serviceY']
$request->amount: [1,2]
$request->description: ['Lorem', 'Ipsum']
So if you tried to create the model you're trying to save in your code you would be doing something like this:
Invoice_Details::create([
'service' => ['serviceX', 'serviceY'],
'amount' => [1,2]
'description' => ['Lorem', 'Ipsum']
]);
Which can not work because those values are not set as Json to the database, and also explains why the createMany is not working, because there's a single object that uses an array of values for each value. What you might want is a situation like this:
Invoice_Details::createMany([
[
'service' => 'serviceX',
'amount' => 1
'description' => 'Lorem'
],
[
'service' => 'serviceY',
'amount' => 2
'description' => 'Ipsum'
]
]);
So you should iterate the request parameters and save a whole array of single models rather than try to stuff everything into a single one.
Also, it's pretty legitimate to ask yourself "Sure, but they all have two parameters, why doesn't it just split them when I use the createMany method?" Well, let's suppose the same situation with different parameters:
$request->service: ['serviceX','serviceY']
$request->amount: [1,2]
$request->description: ['Ipsum']
To which model does that description belong to? We could just go by appearence order, but this kind of assumption might lead to huge problems in case of bad implementations. This sadly means that everytime we need to create multiple models we need to define every single one, even though it means adding an iteration beforehand.
TL;DR: Instead of an array of parameters you need an array of models. Iterate through your parameters and build your models before saving them.
//Supposing you already fetched the arrays and they are all of the same length
$details = [];
foreach($services as $key => $service) {
$invoicedetailModel = new Invoice_detail();
$invoicedetailModel->service = $services[$key];
$invoicedetailModel->amount = $amounts[$key];
$invoicedetailModel->description = $descriptions[$key]);
$details[] = $invoicedetailModel;
}
// code to create and attach the many models

How can I receive a specific index of an validator array of array validation in Laravel?

I validate an array in laravel controller and receive message by using $errors->first('field_name') or $errors or $errors->has('field_name). Now the problem is, I validate an array named vaccine_certificate and I can not receive the error message. Actually I receive the message when show all erros at once. but I want to show it with it's input area. How can I solve it?
$this->validate($request, [
'name' => 'required',
'employee_no' => 'required',
'vaccine_certificate.*' => 'image|mimes:png,jpg|max:2048|dimensions:max_height=200,max_width=200',
//'expertise' => 'required',
]);
Input field looks like
<div class="col-6 form-group">
<label class="control-label " for="vaccine_certificate"><h5 class="h6">Vaccine Certificate <small>(<2mb,png,jpg) </small> </h5></label>
<input class="form-control" type="file" name="vaccine_certificate[]" id="vaccine_certificate" multiple/>
#if ($errors->has('vaccine_certificate'))
<p id="employee_no_checker_message" class="text-danger p-2" onload="changeInputBorderColor('vaccine_certificate')"> {{ $errors->first('vaccine_certificate') }}</p>
#endif
</div>
You can use and see all errors in the error bag of form.
$errors->all()
However, as far as I can see there is no "required" in vaccine_certificate, and your rule is vaccine_certificate.*, that means it should be an array. If you make it vaccine_certificate and required like you did in the name field you can see the error message.
If you need to use array, you can use:
$errors->first('vaccine_certificate.*')
Since it is not "required" it will not throw an error and you can not see it in the $errors variable.

Getting id value from url in controller and displaying values associated laravel

I'm trying to create a ticket management system with laravel jetstream and livewire. In the user page there's a table with all tickets that the user created. When the user clicks on the button to open one specific ticket, it should pass the id of the ticket and redirect to another page where it receives the data of that ticket he clicked, like title, message, etc..
The id is passed through the url, but my main problem is that whenever I try to display that data in the view, nothing shows, no errors either. I think that something might be wrong with my controller.
Here's my route:
Route::get('tickets.answers/{id}', [TicketsController::class, 'answers']);
The button to redirect to that specific ticket:
<a href="{{ url('tickets.answers' . '/'. $ticket->id ) }}" > <x-jet-secondary-button >
See Answer
</x-jet-secondary-button></a>
AnswersController:
public function render(Request $request)
{
$tickets = Ticket::where('id', $request->url('id'));
return view('livewire.tickets.answers', [
'tickets' => $tickets,
]);
}
And how I'm trying to display in my blade:
#foreach($tickets as $key => $ticket)
<!-- This example requires Tailwind CSS v2.0+ -->
<div class="bg-white shadow overflow-hidden sm:rounded-lg">
<div class="px-4 py-5 sm:px-6">
<h3 class="text-lg leading-6 font-medium text-gray-900">
Ticket nº {{$ticket->id}} - {{$ticket->title}}
</h3>
</div>
</div>
#endforeach
In your TicketsController you can fetch the id like this
public function answer(Request $request, int $id)
{
// Use the find() method, instead of where(), when searching for the primary key
$tickets = Ticket::find($id);
// .. more
}
In your routes files you specify an answer method, so use this in your TicketsController.
// See how to name a route
Route::get('tickets.answers/{id}', [TicketsController::class, 'answers'])->name('tickets.answers');
Then use the named route in your view like this:
<a href="{{ route('tickets.answers', ['id' => $ticket->id]) }}">
You can see a similar example in the Laravel docs.

Getting TokenMismatchException in VerifyCsrfToken.php line 53 in Laravel 5.1 while using csrf token

I am getting TokenMismatchException in VerifyCsrfToken.php line 53:
I am using {!!Form::open()!!}
{!!Form::close!!}. When I click the add Button in my form with empty field for the first time, it shows me error as I set the validation rule. But when I click the Add button again without refreshing the page, it shows me the TokenMismatchException error. I have checked with dd() and it shows me the token like this:
array:3 [▼
"_token" => "5dXwRHbz4GNY1tx9OVeWPcOkirVIm0YtpkZufFbr"
"menu_name" => ""
"menu_price" => ""
Here is my form code:
{!! Form::open(array('route' =>'upcoming.store', 'method'=>'POST')) !!}
<div class="col-lg-6 col-sm-offset-3 top-spacing">
<input type="text" name="menu_name" placeholder="Menu Name.." class="form-control">
</div>
<div class="col-lg-6 col-sm-offset-3 top-spacing">
<input type="text" name="menu_price" placeholder="Menu Price.." class="form-control">
</div>
<div class="col-sm-2 col-sm-offset-8 top-spacing">
<button class="btn btn-success">
Add +
</button>
</div>
</div>
{!! Form::close() !!}
Here is my controller store function:
public function store(Request $request)
{
dd($request->all());
$this->validate($request, array(
'menu_name'=>'required',
'menu_price'=>'required',
));
$upcoming = new Upcomingfood;
$upcoming->menu_name=$request->menu_name;
$upcoming->menu_price=$request->menu_price;
$upcoming->save();
Session::flash('success','Food Menu Added Successfullly');
return redirect()->back();
}
Can anyone help?
I have solved this problem by going to
`VerifyCsrfToken.php`
and then I have changed
throw new TokenMismatchException;
by
else{
return redirect()->back();
}
But I am not sure am I right or wrong to apply this way. will it bring any problem in my future work in this project. anyone please make me sure. please.
Try add {{ csrf_field() }} inside the form.
I really recommend that you read official documentation https://laravel.com/docs/5.4/csrf

Laravel applying search filers

I have a page which has a search box(input text) which takes a place name as input and returns all the nearby dealers.
I also happen to have filters (checkboxes) for all the brand
<div class="col-sm-12 col-md-12">
{!! Form::checkbox('filters',$bike_oem, false,['style'=>'padding-right:5px;'] ) !!} <span style="padding-left:5px;"></span>{{ $bike_oem }}
</div>
How do I implement get the value of filter in my controller ?
<div class="col-sm-12 col-md-12">
<input style="padding-right:5px;" name="Hyundai " type="checkbox" value="Y"> <span style="padding-left:5px;"></span>Hyundai
</div>
This is how each filter appears in the page. Is the code correct to fetch the value in controller ? Please suggest
You can get the value of checkbox in this way also(in controller)
public function myFunction(Request $request){
if (isset($request['Hyundai']) && ($request['Hyundai'] == "on")) {
$value = "Y";
}
}

Resources