I am building a form in Laravel, which receives dynamic input. The user can add a link in the input text, but can choose to add more links as desired. The funcionality for that was developing using jquery. The problem is that when I try to save the form (submit), I get this error message.
ErrorException in helpers.php line 531:
htmlentities() expects parameter 1 to be string, array given (View: C:\Users\jkabbas\Documents\GitProects\rastro\src\resources\views\arquiteturas\novo.blade.php)
This is the code excerpt in the laravel page, which is causing the problem. When I remove the square brackets [] from name="txt-link[]", the error message is gone, but I need to use array because I am dealing with multiple inputs.
<td>
<input type="text" placeholder="Digite o link da arquitetura" class="form-control" id="txt-link" name="txt-link[]" value="{{old('txt-link')}}" style="width: 730px;">
#if($errors->has('txt-link'))
#foreach ($errors->get('txt-link') as $message)
<span class="help-block" style="margin-top:5px; margin-bottom:-5px; color:rgb(170, 56, 56)">
<b>{{ $message }}</b>
</span>
#endforeach
#endif
</td>
Backend code
function store(Request $request) {
$this->validate($request, [
'combo_produto'=>['not_in:0'],
'combo_projeto'=>['not_in:0'],
'txt-link[]'=>['required'],
]);
$save_arquitetura = Arquitetura::create([
'produto_id' =>$request['combo_produto'],
'projeto_id' =>$request['combo_projeto'],
]);
return redirect('/arquiteturas')->with('msg_success', 'Dados salvos com sucesso!');
}
this is caused by value="{{old('txt-link')}}". Some kind of error occurred in your backend while you are uploading multiple files and your return all old input but you are not handling it here value="{{old('txt-link')}}. thats is the reason behind htmlentities() expects parameter 1 to be string, array given
Related
TLDR;
(In Laravel 5.8) Upon validation error, how can I return to a specific view with all input and the errors?
I'm creating a multistep form in which I need to validate the input on each step. Therefore, I have created the first page as a create and then the subsequent pages to update.
On the second page, when the validator fails, I am returning the specific view as I want it to go to this partial and not the beginning of the form. I am also returning the errors and the input on fail.
Controller:
if ($validator->fails()) {
return view('partials.question_02_' . $type)
->with('type', $type)
->with('id', $id)
->withErrors($validator)
->withInput($request->all());
}
Here is my validation logic:
$validator = Validator::make($request->all(), [
'email' => 'required',
'first_name' => 'required',
'last_name' => 'required',
'phone' => 'required',
]);
With this, I am able to go back to the specific view and with the validation errors. However, I am not able to receive the old input.
The following in Blade will show that there is an erro (the error class appears), however, it will not show the old input.
<input class="#if ($errors->has('first_name')) error #endif"
type="text" name="first_name" placeholder="First Name" value="{{ old('first_name') }}">
*note, I only put it on two lines for legibility here
What is weird is that if I die and dump the request, I can see all of the input:
dd($request->all());
However, if I try to get it from the session, I don't see any of the input:
#if($errors)
{{var_dump(Session::all())}}
#endif
Any idea why {{ old('first_name') }} isn't working in this case?
Thanks!
You're Returning a view return view() instead you need to return redirect return redirect()as a return view will generate a fresh page and old() will not work.
So instead of
return view('partials.question_02_' . $type)
Use
return redirect()
&in your case
redirect()->action('LoginController#secondPage'); //you controller and method handling your second page
Consider the manual authentication. If the order ID has not been found in database, we redirect user to page with input fields and with error 'wrongOrderId':
public function login(Request $request) {
$inputted_orderId = $request->input('order_id');
$orderIdInDB = DB::table(self::SITE_IN_DEVELOPMENT_TABLE_NAME)
->where(self::ORDER_ID_FIELD_NAME, $inputted_orderId)->first();
if (is_null($orderIdInDB)) {
return Redirect::route('loginToSitesInDevelopmentZonePage')->withErrors('wrongOrderId');
}
}
In this example, we don't need to pass the error message: the message box is already exists in View; all we need is to display this message box when user has been redirected with error 'wrongOrderId':
#if (!empty($errors->first('wrongOrderId')))
<div class="signInForm-errorMessagebox" id="invalidID-errorMessage">
<!-- ... -->
</div>
#endif
All above code is working without laravel/php errors; I get into is_null($orderIdInDB) if-block when input wrong order number, however the error message box don't appears. I tried a lot of ways, and (!empty($errors->first('wrongOrderId'))) is just last one. What I doing wrong?
Did you try printing {{$errors->first()}}?
first(string), works as a key value pair, it invokes its first key VALUE
try this,
#if($errors->any())
<div class="signInForm-errorMessagebox" id="invalidID-errorMessage">
<!-- ... -->
</div>
#endif
If you want to get specific error from validator error, use the get() method.
$errors->get('wrongOrderId'); get all the wrongOrderId errors.
$errors->first('wrongOrderId'); get first error of wrongOrderId errors
I explored that $errors->first('wrongOrderId') has non-displayable but non-null value. So #if ( $errors->first('wrongOrderId') !== null ) will work.
Something more elegantly like #if ($errors->first('wrongOrderId'))? Unfortunately just one this check is not enough: even if we define
return Redirect::route('loginToSitesInDevelopmentZonePage')->withErrors(['wrongOrderId' => true]);
php will convert true to 1. So, #if ( $errors->first('wrongOrderId') == true ) will working, but #if ($errors->first('wrongOrderId')) will not.
However, we can to cast $errors->first('wrongOrderId') to bool, so the most elegant solution will be
#if ((bool) $errors->first('wrongOrderId'))
Quoting laravel documentation:
Likewise, you may use the * character when specifying your validation messages in your language files, making it a breeze to use a single validation message for array based fields:
'custom' => ['person.*.email' => ['unique' => 'Each person must have a unique e-mail address']]
It seems it does not work. I have a validation message:
'infos.*.*.*' => ['required' => 'My text']
Then I have some inputs in my view:
<input type="text" name="infos[1234][0][name]">
<input type="text" name="infos[1234][1][name]">
<input type="text" name="infos[5678][0][name]">
And in my controller I validate the input:
$this->validate($request, [
'infos.*.*.*' => 'required'
]);
And in view I have a error displayer:
#if (count($errors) > 0)
<strong>Oops. Errors:</strong>
<ul>
#foreach ($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
#endif
And if I leave all input empty I got:
My text
My text
My text
My text
My text
etc.
What's wrong with my code? Reading Laravel documentation I though it should have worked (I mean: it should have been displayed only once). Did I misunderstood something?
This is working as intended. Since you're passing multiple inputs in an array, the validation throws an error for each item. Therefore 3 inputs with 2 causing errors and 1 passing would obviously pass error for 2 inputs. So in your case the multiple errors are due to multiple inputs failing validation.
I have a problem with laravel, and my form.
In my form (createBand.blade.php), i made a form with a dropdownlist wich call a database table: musicalGenre.
It should be noted that the dropdownmenu/list (select form) calls to another table in the database called MusicalGenre, and the form where I want the dropdownlist is to register a band in the database table Bands.
The select form works, i could choose in a dropdownlist all musicalGenre_name in my table after seeding them. Here's the blade page code (of course i have open, close the form and the section like laravel requires):
<p>
{{Form::label('name','Name of the Band: ')}}
{{Form::text('name',Input::old('name'))}}
</p>
#if ($errors->has('name'))
<p class='error'> {{ $errors->first('name')}}</p>
#endif
<br>
<br>
<p>
{{Form::label('email','Band Email: ')}}
{{Form::text('email',Input::old('email'))}}
</p>
#if ($errors->has('email'))
<p class='error'> {{ $errors->first('email')}}</p>
#endif
<br>
<br>
<p>
{{Form::label('musicalGenre','your style: ')}}
{{Form::select('musicalGenre_name', $genre_options = array('' => 'select your style') + musicalGenre::lists('name'), Input::old('musicalGenre_name')) }}
</p>
#if ($errors->has('musicalGenre'))
<p class='error'> {{ $errors->first('musicalGenre_name')}}</p>
#endif
<br>
<br>
I have a controller named createBandController, where i made some rules for validators for the blade form. The poblem is:
i can't pass the validators, that is to say, even if i choose a musical genre in my dropdownlist, for laravel there no choice made.
I have the error "musical genre is required". I don't understand the validator rules for a select form in my controller, or i don't know what i'm suposed to input in the rules for musical genre. Here's the controller code:
public function createBand() {
$result = MusicalGenre::all();
$genre = $result->lists('name');
$inputs = Input::all();
$rules = array(
'name' => 'required|between:1,64|unique:bands,name',
'email' => 'between:1,128|email|unique:bands,email',
'musicalGenre' => 'integer|required|in:musicalGenre'
);
$validation = Validator::make($inputs, $rules);
if ($validation->fails()) {
return Redirect::to('createBand')->withInput()->withErrors($validation)
->with('alert_error', 'you have some mistakes');
Don't pay attention to the names, (i'm french, i changed them in order to be clear for you), and i'm sure that is the validator of my dropdownlist who make problems when i fill out my form, because i can't pass it. In my original project code, there are no spelling mistakes.
All my validators and variable names work. I think i need to find the correct rules for a select form input and validators in order to laravel knows i made a choice when i choose in my dropdownlist.
At first i thought to specify that the dropdownlist use the database table musicalGenre. Like i specified that some fields are in the database table Bands, like this:
'name' => 'required|between:1,64|unique:bands,name'
Here, "name" is a field of the database table Bands. But it didn't work too.
If anyone have a solutions or wants to help, i'm interested.
Thank you (and sorry if my english seems so bad).
The validation rule in: on the field musicalGenre won't work the way that you have implemented it. It expects a comma delimited list of strings which the field value is scrubbed against.
For example if the field was 'Gender' the validation would be:
'gender' => 'in:male,female'
To validate against musicalGenre against a model you will need to write a custom Validator. See http://laravel.com/docs/validation#custom-validation-rules
I am currently writing a custom validator for this 'belongs_to' validation and when I have it working I'll post it here.
UPDATE
I have written a custom validation rule that should help. Firstly create a validators.php file and include it in global.php
require app_path().'/validators.php';
Within validators.php create the custom rule:
Validator::extend('exists_in', function($attribute, $value, $parameters)
{
$result = $parameters[0]::find($value);
return ($result == null) ? FALSE : TRUE;
});
In your validations you could now have:
'musicalGenre' => 'integer|required|exists_in:musicalGenre'
The exists_in validation takes a parameter of the Model Class name
And to give this validation an error message, add the following to the array in app/lang/en/validation.php:
"exists_in" => "The selected :attribute is invalid."
Does exists:musicalGenre instead of in:musicalGenre help?
Is there any utility function in Laravel that allows you to give an alternative value for a specific input field if the old value is empty? Currently I have the following code:
<input type="text" class="form-control" id="title" name="title" value="{{ (!empty(Input::old('title'))) ? Input::old('title') : 'hey' }}">
But its not really that pretty. Any ideas?
use
Input::old('title', 'fallback value')
Yes! Don't use the input tag :)
If you use {{ Form you will get this, and much, much more!
{{ Form::text('email', null, array('class'=>'form-control', 'placeholder'=>'Email Address')) }}
Check out the docs here (http://laravel.com/docs/html & http://laravel.com/docs/requests) and you will notice that when the input is flashed to the session, this input box rendered by blade will automatically replace that "null" (the second parameter) with the flashed value from the session.
This removes the need to check for the old input or have any nasty if/else checks inside your template. Also, you no longer need to worry about any HTML code injections or XSS happening, because Form::text will ensure that the text is correctly converted to their HTML entities.
Where you are checking for errors, you should use a Laravel validator. Something similar to this:
protected function createUser(){
$rules = array(
'email'=>'required|email',
'password'=>'required|min:6|confirmed',
'password_confirmation'=>'required'
);
$validator = Validator::make(Input::all(), $rules);
if (! $validator->passes()) {
Input::flashExcept('password', 'password_confirmation');
return Redirect::to('my_form');
} else {
// do stuff with the form, it's all good
}
return Redirect::intended('/complete');
}
Additionally, in your template, you can show all of the errors from the form:
<ul>
#foreach($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
Or just select the first error and show it under the {{ Form::text
#if ($errors->has('first_name'))
<span class="error">{{$errors->first('first_name')}}</span>
#endif
Laravel has all of this built in, and you get it for free! Using Requests, Validators, Blade/HTML