How to use custom validation attributes on an array of inputs - laravel

I'm using Laravel to build a form that contains an array of inputs and I’m having difficulty in showing the translated attribute name when a validation error occurs. For simplicity sake I will post a simple example of my problem.
Form inside the view:
<form method="POST" action="{{ route('photo.store') }}" accept-charset="UTF-8" role="form">
<input name="_token" type="hidden" value="{{ csrf_token() }}">
<div class="row">
<div class="col-lg-12">
<div class="form-group{{ $errors->has('testfield') ? ' has-error' : '' }}">
<label class="control-label"
for="testfield">{{ trans('validation.attributes.testfield') }}</label>
<input class="form-control" name="testfield" type="text" id="testfield"
value="{{ old('testfield') }}">
#if ($errors->has('testfield'))
<p class="help-block">{{ $errors->first('testfield') }}</p>
#endif
</div>
</div>
<div class="col-lg-12">
<div class="form-group{{ $errors->has('testfieldarray.0') ? ' has-error' : '' }}">
<label class="control-label"
for="testfieldarray-0">{{ trans('validation.attributes.testfieldarray') }}</label>
<input class="form-control" name="testfieldarray[]" type="text" id="testfieldarray-0"
value="{{ old('testfieldarray.0') }}">
#if ($errors->has('testfieldarray.0'))
<p class="help-block">{{ $errors->first('testfieldarray.0') }}</p>
#endif
</div>
</div>
<div class="col-lg-12">
<div class="form-group{{ $errors->has('testfieldarray.1') ? ' has-error' : '' }}">
<label class="control-label"
for="testfieldarray-1">{{ trans('validation.attributes.testfieldarray') }}</label>
<input class="form-control" name="testfieldarray[]" type="text" id="testfieldarray-1"
value="{{ old('testfieldarray.1') }}">
#if ($errors->has('testfieldarray.1'))
<p class="help-block">{{ $errors->first('testfieldarray.1') }}</p>
#endif
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<input class="btn btn-primary" type="submit" value="Gravar">
</div>
</div>
Rules function in the form request:
public function rules() {
$rules = [
'testfield' => array('required'),
];
foreach ($this->request->get('testfieldarray') as $key => $val) {
$rules['testfieldarray.' . $key] = array('required');
}
return $rules;
}
lang/en/validation.php
'attributes' => [
'testfield' => 'Test Field',
'testfieldarray' => 'Test Field Array',
],
The validation is performed correctly, as do the error messages. The only problem in the error messages is the name of the attribute displayed. In both array inputs, the attribute name inserted in the message is 'testfieldarray.0' and 'testfieldarray.1' instead of 'Test Field Array'. I already tried to add on the language file 'testfieldarray.0' => 'Test Field Array', 'testfieldarray.1' => 'Test Field Array', but the messages remain unchanged. Is there a way to pass the attribute names correctly?

Just see the example to add custom rules for integer type value check of array
Open the file
/resources/lang/en/validation.php
Then add the custom message.
// add it before "accepted" message.
'numericarray' => 'The :attribute must be numeric array value.',
Again Open another file to add custom validation rules.
/app/Providers/AppServiceProvider.php
So, add the custom validation code in the boot function.
public function boot()
{
$this->app['validator']->extend('numericarray', function ($attribute, $value, $parameters)
{
foreach ($value as $v) {
if (!is_int($v)) {
return false;
}
}
return true;
});
}
Now you can use the numericarray for integer type value check of array.
$this->validate($request, [
'input_filed_1' => 'required',
'input_filed_2' => 'numericarray'
]);
----------- Best of Luck --------------

1-if you split the validation in file request then add the method attributes and set the value of each key like this :
public function attributes()
{
return [
'name'=>'title',
];
}
2- but if don't split the validation of the request then you just need to make variable attributes and pass the value of items like this :
$rules = [
'account_number' => ['required','digits:10','max:10','unique:bank_details']
];
$messages = [];
$attributes = [
'account_number' => 'Mobile number',
];
$request->validate($rules,$messages,$attributes);
// OR
$validator = Validator::make($request->all(), $rules, $messages, $attributes);

Use custom error messages inside your parent method....
public function <metod>(Request $request) {
$rules = [
'testfield' => 'required'
];
$messages = [];
foreach ($request->input('testfieldarray') as $key => $val) {
$rules['testfieldarray.' . $key] = 'required';
$messages['testfieldarray.' . $key . '.required'] = 'Test field '.$key.' is required';
}
$validator = Validator::make($request->all(), $rules,$messages);
if ($validator->fails()) {
$request->flash();
return redirect()
->back()
->withInput()
->withErrors($validator);
}
}
}

Related

Can't upload files using livewire

I can't submit a form with file in order to proced to upload method, the file is selected when I submit it says that the file is required (empty data).
Everything works fine on mylocal Windows machine but I face the problem when using vps for production.
view :
<form wire:submit.prevent="submit" enctype="multipart/form-data">
<div>
#if(session()->has('message'))
<div class="alert alert-success">
{{ session('message') }}
</div>
#endif
</div>
<div class="form-group">
<label for="exampleInputName">Title:</label>
<input type="text" class="form-control" id="exampleInputName" placeholder="Enter title" wire:model="title">
#error('title') <span class="text-danger">{{ $message }}</span> #enderror
</div>
<div class="form-group">
<label for="exampleInputName">File:</label>
<input type="file" class="form-control" id="exampleInputName" wire:model="file">
#error('file') <span class="text-danger">{{ $message }}</span> #enderror
</div>
<button type="submit" class="btn btn-success">Save</button>
</form>
controller :
use WithFileUploads;
public $file, $title;
public function submit()
{
$validatedData = $this->validate([
'title' => 'required',
'file' => 'required',
]);
$validatedData['name'] = $this->file->store('files', 'public');
// File::create($validatedData);
session()->flash('message', 'File successfully Uploaded.');
}
VPS folders :
I tried to change permessions, user group.... no success.
try this
use WithFileUploads;
public $title;
public $file;
protected function rules()
{
return [
'title' => ['required', 'string', 'max:50'],
'file' => ['required', 'file', 'mimes:pdf,doc,docx', 'max:5000']
];
}
public function submit()
{
$this->validate();
$data = [
'title' => $this->title
];
if (!empty($this->file)) {
$url = $this->file->store('files', 'public');
$data['file'] = $url;
}
File::create($data);
session()->flash('message', 'File successfully Uploaded.');
}

Laravel Must be string when saving

I have a mounted variable and an error occurs when i'm about to save the variable.
public $code;
public function mount()
{
$this->code = substr(str_shuffle(str_repeat("ABCDEFGHIJKLMNOPQRSTUVWXYZ", 5)), 0, 3).Carbon::now()->format('md').rand(100, 999);
}
protected function rules(): array
{
return [
'applicant.code' => [
'string',
'required',
],
];
}
blade
<div class="form-group {{ $errors->has('applicant.code') ? 'invalid' : '' }}">
<label class="form-label" for="code" hidden>{{ trans('cruds.applicant.fields.code') }}</label>
<input class="form-control" type="text" name="code" id="code" value="{{ $code }}" disabled hidden>
<div class="validation-message">
{{ $errors->first('applicant.code') }}
</div>
<div class="help-block">
{{ trans('cruds.applicant.fields.code_helper') }}
</div>
</div>
<div class="form-group">
<button class="btn btn-indigo mr-2" type="submit">
{{ trans('global.submit') }}
</button>
<a href="{{ route('admin.applicants.index') }}" class="btn btn-secondary">
{{ trans('global.cancel') }}
</a>
</div>
The code must be a string.
I can't seem to figure out this error. Can anyone help?
<input class="form-control" type="text" name="code" id="code" value="{{ $code }}" disabled hidden>
Your input code is disabled
function mount() {
$characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
$date = date("md");
$numbers = rand(100, 999);
$randomString = substr(str_shuffle(str_repeat($characters, 5)), 0, 3). $date . $numbers;
return $randomString;
}
echo mount();
Your rule defines applicant.code, therefore the validation is expecting a variable named applicant with a key named code:
public array $applicant = [
'code' => null,
];
public function mount()
{
$this->applicant['code'] = ''; // Implement your code
}
Also, you have an input showing the code in your blade view. Is this meant to be editable? If so, you should be using wire:name instead of name (See docs).
However, since you have it disabled, I don't assume you want to allow the user to edit it, so why have it validated in the first place?

Laravel Custom Validation of Two Dates

I'm creating a form in Laravel which has two fields: departure-date and return-date. I'm trying to create custom validation logic where the departure date entered MUST be on the same day or any other date after the user fills in the form. The return-date should also be after the departure date. Kindly assist?
Form Layout
<!-- Departure date-->
<div class="form-line registar2 love {{ $errors->has('departure_date') ? ' has-error' : '' }}">
<input type="date" class="form-input" name="departure_date" value="{{ old('departure_date') }}" required>
<label>Departure Date *</label>
<div class="error-label">Field is required!</div>
<div class="check-label"></div>
#if ($errors->has('departure_date'))
<span class="help-block">
<strong>{{ $errors->first('departure_date') }}</strong>
</span>
#endif
</div>
<!--End departure-->
<!-- Return date-->
<div class="form-line registar2 move {{ $errors->has('return_date') ? ' has-error' : '' }}">
<input type="date" class="form-input" name="return_date" value="{{ old('return_date') }}" required>
<label>Return Date *</label>
<div class="error-label">Field is required!</div>
<div class="check-label"></div>
#if ($errors->has('return_date'))
<span class="help-block">
<strong>{{ $errors->first('return_date') }}</strong>
</span>
#endif
</div>
<!-- End return date-->
Validation in Controller
public function validatePlanEntries(Request $request)
{
$validation = $this->validate($request, [
'departure_date' => 'required',
'return_date' => 'required'
]
);
}
public function validatePlanEntries(Request $request)
{
$validation = $this->validate($request, [
'departure_date' => 'required|date|after:now',
'return_date' => 'required|date|after:departure_date',
]
);
}
FYI: the after:xxxxx rule either compares to another input field or respects the rules of the native DateTime PHP class. So you may enter after:now +2 hours.
To override the messages and write your own, create a messages() function like this:
public function messages()
{
return [
'departure_date.required' => 'Departure date is required',
'departure_date.after' => 'Please choose a date in the future',
'return_date.required' => 'Return date is required',
'return_date.after' => 'Your return date is before departure'
];
}
Just in case you are looking for a jquery solution to make datepicking more user friendly and less error bound, you may have a look at Bootstrap Datepicker, it's probably worth the effort. Good luck on your project!

Validation errors are not output and fields with previous Form data are not returned

Laravel 5.2
view where the form of sending data ('blade'):
#if( count($errors) > 0 )
<div class="alert alert-danger">
<ul>
#foreach( $errors->all() as $error ) <li>{{ $error }}</li> #endforeach
</ul>
</div>
#endif
<form method="POST" action="{{ route('contact') }}"> <!-- <?//='/contact');?> Or <?//=route('contact');?> -->
<input type="hidden" name="_token" value="{{ csrf_token() }}">
<div class="form-group">
<label for="name">Name:</label>
<input type="text" class="form-control" id="name" name="name" value="{{ old('name') }}" placeholder="Enter Name">
</div>
<div class="form-group">
<label for="email">Email address:</label>
<input type="email" class="form-control" id="email" name="email" value="{{ old('email') }}" placeholder="Enter E-mail">
</div>
<div class="form-group">
<label for="site">Site:</label>
<input type="text" class="form-control" id="site" name="site" value="{{ old('site') }}" placeholder="Enter Site">
</div>
<div class="form-group">
<label for="text_area">Text:</label>
<textarea class="form-control" id="text_area" name="text_area" rows="3" placeholder="Some text....."> {{ old('text_area') }} </textarea>
</div>
<div class="checkbox">
<label><input type="checkbox" name="checkbox"> Remember me</label>
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
</div> <!--/class="col-"-->
</div> <!--/class="row"-->
ContactController.php
namespace App\Http\Controllers\Admin;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;
class ContactController extends Controller {
public function show( Request $request, $prm=false ){
$my_array = ['title1'=>'This variable `$title1` content', 'title2'=>'This variable `$title2` content', 'title3'=>'This variable `$title3` content']; //массив
$my_array2 = ['one'=>array('param1'=>'This variable `param1` content', 'param2'=>'This variable `param2` content', 'param3'=>'This variable `param3` content'),
'two'=>array('param4'=>'This variabl e `param4` content', 'param5'=>'This variable `param5` content', 'param6'=>'This variable `param6` content')
];
$my_array3 = array(
'title'=>'Contact',
'data'=>[ 'one'=>'list 1',
'two'=>'list 2',
'three'=>'list 3',
'four'=>'list 4',
'five'=>'list 5',
],
'dataI'=>['list-1','list-2','list-3','list-4','list-6','list-6'],
'bvar'=>true,
'script'=>"<script>alert('Hello! ++')</script>"
);
/** VALIDATION on Request */
if( $request->isMethod('post') ) {
$rules = [
'name' => 'required|max:10',
'email' => 'required|email',
//'site'=>'required',
//'text_area'=>'required',
];
$messages = [
'required' => 'The :attribute field is required.',
];
$this->validate($request, $rules, $messages);
dump( $request->all() );
dump( $request->session()->all() );
}
if( view()->exists('default.contact') ){
return view('default.contact')
->withMydata($my_array2)
->withMydata2($my_array)
->withMydata3($my_array3);
}
else { abort(404); }
}
}
/app/Http/Kernel.php
/**
* The application's global HTTP middleware stack.
*
* These middleware are run during every request to your application.
*
* #var array
*/
protected $middleware = [
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
];
How can I see that validation fulfills and its rules are in effect,
But I do not see the display of validation errors when it is not passed and the data in the input fields when the Form is filled when redirecting back.
Let me show you my method which also uses validation on Laravel 5.2 and find out what the difference you have with this code:
The Controller which handles the request:
$validator = \Validator::make($request->all(), [
'data1' => 'required',
'data2' => 'required|in:bla1,bla2,bla3',
'data3' => 'required|array',
'data3.*' => 'required|json',
'data4' => 'required_if:data2,bla2',
]);
if ($validator->fails()) {
$request->flash();
return \Response::make(\View::make('theform')
->withErrors($validator)
->withInput($request->all())
->render()
, 406);
}
The form which contains the form which has been submitted and redrawn with error logs, named 'theform':
<input type="text" class="form-control" name="trip_name" id="trip_name"
placeholder="Gezi ismi" value="{{ old('trip_name') }}">
#if ($errors->has('trip_name'))
<span class="help-block">
<strong>{{ $errors->first('trip_name') }}</strong>
</span>
#endif
This is one way to show it. You can also view it your way as:
#if( count($errors) > 0 )
<div class="alert alert-danger">
<ul>
#foreach( $errors->all() as $error )
<li>{{ $error }}</li>
#endforeach
</ul>
</div>
#endif
Well, the problem did not stop there ))
I create the validation through my own class Request and divide routes for GET and POST and defined separate methods for them in my Controller.
1. app/Http/routes.php
Route::get('/contact_form/{prm?}', ['uses'=>'Admin\ContactformController#show_form_get'])->name('contact_form');
Route::post('/contact_form', ['uses'=>'Admin\ContactformController#show_form_post']);
2. app/Http/Requests/ContactRequest.php - my custom Request class with validation rules:
<?php
namespace App\Http\Requests;
use App\Http\Requests\Request;
class ContactRequest extends Request
{
public function authorize()
{
return true; //false
}
public function rules()
{
return [
'name' => 'required|max:10',
//'name' => 'exists:users,name',
'email' => 'required|email',
'site'=>'required',
];
}
} //__/class ContactRequest
3. app/Http/Requests/ContactRequest.php - my Controller with POST and GET handling:
<?php
namespace App\Http\Controllers\Admin;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Requests\ContactRequest; //custom Request class with validation rules
use App\Http\Controllers\Controller;
use \Illuminate\Support\Facades\Validator;
class ContactformController extends Controller {
public $show_controller_method = array(__METHOD__);
/** Method handler http-request with GET
*/
public function show_form_get( ){
$this->show_controller_method[] = 'showform()';
if( view()->exists('default.contact_form') ){
return view('default.contact_form')->withInfoMethodController($this->show_controller_method);
}
else { abort(404); }
} //__/public function show_form_get()
/** Method handler http-request with POST
*/
public function show_form_post( ContactRequest $request ){
if( $request->isMethod('post') ):
dump( $request->all() );
endif;
}
3. The view remained the same and there is a return of data "old inputs":
value="{{ old('name') }}" value="{{ old('email') }}" and so on...
and errors of validation if they exist:
#if( count($errors) > 0 )
<div class="alert alert-danger">
<ul>
#foreach( $errors->all() as $error ) <li>{{ $error }}</li> #endforeach
</ul>
</div>
#endif
Now the validation works (if it passes successfully - I see a dump() the POST.
If the validation falls, then a redirect occurs, but there are no validation errors and there are no old inputs.
Tell me please what I'm doing is not right?

Laravel - How to handle errors on PUT form?

I am working with laravel 5.2 and want to validate some data in an edit form. I goal should be to display the errors and keep the wrong data in the input fields.
My issue is that the input is validated by ContentRequest and the FormRequest returns
$this->redirector->to($this->getRedirectUrl())
->withInput($this->except($this->dontFlash))
->withErrors($errors, $this->errorBag);
which is fine so far. Next step the edit action in the controller is called and all parameters are overwritten.
What I have currently done:
ContentController:
public function edit($id)
{
$content = Content::find($id);
return view('contents.edit', ['content' => $content]);
}
public function update(ContentRequest $request, $id)
{
$content = Content::find($id);
foreach (array_keys(array_except($this->fields, ['content'])) as $field) {
$content->$field = $request->get($field);
}
$content->save();
return redirect(URL::route('manage.contents.edit', array('content' => $content->id)))
->withSuccess("Changes saved.");
}
ContentRequest:
class ContentRequest extends Request
{
public function authorize()
{
return true;
}
public function rules()
{
return [
'title' => 'required|min:3',
'body' => 'required|min:3'
];
}
}
How can I fix this? The form looks like this:
<form action="{!! URL::route('manage.contents.update', array('content' => $content->slug)) !!}"
id="site-form" class="form-horizontal" method="POST">
{!! method_field('PUT') !!}
{!! csrf_field() !!}
<div class="form-group {{ $errors->has('title') ? 'has-error' : '' }}">
<label for="title" class="col-sm-2 control-label">Title</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="title" id="title" placeholder="Title"
value="{{ $content->title }}">
#if ($errors->has('title'))
<span class="help-block">
<strong>{{ $errors->first('title') }}</strong>
</span>
#endif
</div>
</div>
</form>
Try something like the following:
<input
type="text"
class="form-control"
name="title"
id="title"
placeholder="Title"
value="{{ old('title', $content->title) }}" />
Note the value attribute. Also check the documentation and find Retrieving Old Data.

Resources