Laravel 5 validate cloned fields using form request - php

I have a form using cloneya jQuery plugin to clone form elements. The elements that will be cloned looks like so:
<div class="form-group">
<label for="name">Item name</label>
<input class="form-control" name="name[]" type="text">
</div>
<div class="form-group">
<label for="count">Item count</label>
<input class="form-control" name="count[]" type="text">
</div>
As you can see, each input will be an array instead of string. I want to validate those using Laravel Form Request. Here's my rules:
public function rules()
{
return [
'name' => 'required|between:3,50',
'count' => 'required|integer|min:1',
];
}
But that's not working. When I submitted the form, I got the following error message:
htmlentities() expects parameter 1 to be string, array given
I've been searching for solution, but can't find the appropriate one. Any suggestion would be appreciated!

Basically, in your rules() method, you need to determine how many name and count elements there are in the POST and then create rules for each of them:
public function rules()
{
$rules = [];
foreach ($this->request->get('name') as $index => $val) {
$rules['name.' . $index] = 'required|between:3,50';
}
foreach ($this->request->get('count') as $index => $val) {
$rules['count.' . $index] = 'required|integer|min:1';
}
return $rules;
}
Please check this post.

Related

How to store multiple checkbox values to database in Laravel?

I need to store checkbox values into the database. I have tried so many examples, but still am not able to do that, Here I will give you my code and give me the solution for this.
My Blade File
<div class="form-group row">
<label for="hobbies" class="col-md-4 col-form-label text-md-right">Hobbies</label>
<div class="col-md-6">
<input type="checkbox" name="hobbies[]" value="Readbooks"/> Readbooks
<input type="checkbox" name="hobbies[]" value="Games"/> Games
<input type="checkbox" name="hobbies[]" value="Music"/> Music
#if ($errors->has('hobbies'))
<span class="text-danger">{{ $errors->first('hobbies') }}</span>
#endif
</div>
</div>
My Controller File
public function postRegistration(Request $request)
{
$data = $request->all();
$check = $this->create($data);
return redirect("login")->withSuccess('Great! please login.');
}
public function create(array $data)
{
return User::create([
'hobbies' => $data->implode([',', (array) $data->get('hobbies')]),
]);
}
Error:Call to a member function implode() on array
This is not how you use the implode method. And like the error says; you try to call a method on an array, because $data is an array and not an object.
And last, $data->get('hobbies') will also cause you problems, because the get() helper is not working on an array.
This is what you need:
return User::create([
'hobbies' => implode(',', (array) $data['hobbies']),
]);
When you have inputs like:
<input type="checkbox" name="hobbies[]" value="Readbooks"/> Readbooks
<input type="checkbox" name="hobbies[]" value="Games"/> Games
<input type="checkbox" name="hobbies[]" value="Music"/> Music
The POST data received by the server includes hobbies as an array. You can confirm this by inspecting the received request in your controller:
public function postRegistration(Request $request) {
dd($request);
}
Since $request->hobbies is already an array, there is no need to cast it with (array).
In the code you've shown, you are trying to implode() your hobbies. implode() generates a string, so if the hobbies field you are trying to populate in the database is a string, you simply need to implode that received array of hobbies:
// Will generate a string like: "Readbooks,Music"
implode(',', $request->hobbies);
Putting it into your code:
public function create($data) {
return User::create(['hobbies' => implode(',', $data->hobbies)];
}

Laravel Returned a Blank Page with "IF" validation

I am new to laravel and I am trying to solve this problem. I want to make validation, the user must select at least 3 values before he can proceed. I tried to use count($array) but it's not working, I know I am doing something wrong, but I don't what. When I tried the code before it returned a blank page
In my onboarding.blade.php, I have this form
<form action="{{ url('/onboarding') }}" method="POST">
#csrf
#foreach($categories as $category)
<div class="radio-item">
<!-- <input class="form control" name="category_id" value="{{$category->id}}" type="hidden"> -->
<input type="checkbox" id="category_id" name="category_id[]" value="{{$category->id}}">
<label for="name">{{ $category -> title }}</label>
</div>
#endforeach
<div class="form-row">
<div class="form-group col-md-12 text-center">
<button type="submit">Proceed to Authors</button>
</div>
</div>
</form>
In my OnboardsController.php I have this
public function categoryUser (Request $request)
{
$category_id = request('category_id');
if (count($category_id) >= 3) {
$user = Auth::user();
$user->categories()->attach($request->input('category_id'));
return redirect ( route ('onboarding_author'));
}
}
On a side note, you could actually use the validator if you would like. You could use rules like so:
'category_id' => 'array|min:3',
'category_id.*' => 'integer',
You can use the Request object to do quick validation:
public function categoryUser(Request $request)
{
$request->validate([
'category_id' => 'array|min:3',
'category_id.*' => 'integer',
]);
// ... passed validation
}
If this fails validation it will end up causing a redirect back.
Laravel 6.x Docs - Validation - Available Rules - array
Laravel 6.x Docs - Validation - Available Rules - min
Laravel 6.x Docs - Validation - Quick Start - Writing the Validation Logic
What if your condition is false! you don't write. So move your return statement outside the if condition
public function categoryUser (Request $request)
{
$category_id = request('category_id');
if (count($category_id) >= 3) {
$user = Auth::user();
$user->categories()->attach($request->input('category_id'));
}
return redirect ( route ('onboarding_author'));
}
I think lagbox's solution is correct but if you don't wanna redirect your user directly you can manually redirect him with following method:
if ($validator->fails()) {
// Validation Fails Here...
return redirect()->back()->withErrors($validator)->withInput();
}

Inserting a two diminsionale array in database from multiple dynamic fields - Laravel

Using Laravel I created a form where dynamically input fields can be added and remove using jQuery.
I am now trying to insert the data into the database, there I encounter a problem. My database exists of two tables; Tasks and issues.
The 'issue' table is linked to the tasks table bij task_id. This task_id should be also sent to the database but I can't get it, wright. See my code below.
Thanks for the help.
IssueController.php
The first method works but then my task id "null". All records are inserted from all fields.
The second method only adds the data of 1 field but it adds the correct id.
public function store(Request $request, Issue $issue, Task $task)
{
## First method
// foreach($request->issueInfo as $key => $value) {
// Issue::create($value);
// }
## Second method
foreach ($request->issueInfo as $key => $name) {
dd($name);
$names[] = [
'task_id' => $task->id,
'issue_name' => $name,
'issue_time' => $name,
'issue_date' => $name,
'issue_type' => $name,
];
}
Issue::insert($names);
return back();
}
web.php
Route::post('/tasks/{task}/issues', 'IssueController#store');
show.blade.php
#extends('layout')
#section('content')
<script>
$(document).ready(function() {
var i = 1;
$('.addmore').click(function(){
i++;
$('#dynamicFields').append('<div class="form-group"><label for="issue_name">Issue Name</label><select class="form-control" name="issueInfo['+i+'][issue_name]"><option></option><option value="Error">Error</option><option value="Grammer">Grammer</option><option value="Undefined">Undefined</option><option value="Typpo">Typpo</option><option value="No errors">No errors</option></select></div><div class="form-group"><label for="issue_date" class="label">Issue Date</label><input class="form-control" type="date" name="issueInfo['+i+'][issue_date]"></div><div class="form-group"><label for="issue_time" class="label">Issue Time</label><input class="form-control" type="time" name="issueInfo['+i+'][issue_time]" ></div><div class="form-group"><label for="issue_type" class="label">Issue Type</label><select class="form-control" name="issueInfo['+i+'][issue_type]"><option></option><option value="False45">False45</option><option value="False104">False104</option></select></div><div class="form-group"><button type="button" class="btn btn-danger remove-field">Remove</button></div>');
});
// Removing fields
$('#dynamicFields').on('click', '.remove-field', function(){
$(this).parents('div').remove(); i--;
})
});
</script>
<div class="form-group"><label for="issue_name">Name</label></div>
<head>Testing the creation of multiple fields</head>
<form action="/tasks/{{$task->id}}/issues" method="post" >
#csrf
<div id="dynamicFields">
<div class="form-group">
<label for="issue_name">Issue Name</label>
<select class="form-control" name="issueInfo[0][issue_name]">
<option></option>
<option value="Error">Error</option>
<option value="Grammer">Grammer</option>
<option value="Undefined">Undefined</option>
<option value="Typpo">Typpo</option>
<option value="No errors">No errors</option>
</select>
</div>
<div class="form-group">
<label for="issue_date" class="label">Issue Date</label>
<input class="form-control" type="date" name="issueInfo[0][issue_date]" value="{{old('issue_date')}}">
</div>
<div class="form-group">
<label for="issue_time" class="label">Issue Time</label>
<input class="form-control" type="time" name="issueInfo[0][issue_time]" value="{{old('issue_time')}}">
</div>
<div class="form-group">
<label for="issue_type" class="label">Issue Type</label>
<select class="form-control" name="issueInfo[0][issue_type]">
<option></option>
<option value="False45">False45</option>
<option value="False104">False104</option>
</select>
</div>
<div class="form-group">
<input type="button" name="submit" id="submit" class="btn btn-primary addmore" value="+" />
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">New Location</button>
</div>
</div>
</form>
#endsection
Output when I do dd($names) in my controller
array:1 [▼
0 => array:5 [▼
"task_id" => 1
"issue_name" => array:4 [▼
"issue_name" => "Error"
"issue_date" => null
"issue_time" => null
"issue_type" => null
]
"issue_time" => array:4 [▼
"issue_name" => "Error"
"issue_date" => null
"issue_time" => null
"issue_type" => null
]
"issue_date" => array:4 [▶]
"issue_type" => array:4 [▶]
]
]
Here you can find a link to fiddle
You should try the following. I adapted your code a bit in the fiddle. Instead of pushing everything in the same array, store every element in a separate array. In the fiddle, you find the adapt code. In your controller, you should do the following. You should also remove Issue $issue because you are not using it.
Fiddle
public function store(Request $request, Task $task)
{
//
foreach ($request->issue_name as $index => $name) {
$task->issues()->create([
'issue_name' => $name,
'issue_time' => $request->issue_time[$index],
'issue_date' => $request->issue_date[$index],
'issue_type' => $request->issue_type[$index]
]);
}
return back();
}
To solve your problem with the remove button. Add to your class row for example "remove-this-field". And adapt your javascript code for the removal of the fields to:
$('#dynamicFields').on('click', '.remove-fields', function(){
$('.remov-this-field').remove(); i--;
})
Use built-in Eloquent methods to your advantage. First, define relationships:
class Task
{
public function issues()
{
return $this->hasMany(Issues::class);
}
{
class Issue
{
public function task()
{
return $this->belongsTo(Task::class);
}
{
Next, write a good helper method. Note the create() method already takes an array input, so you don't have to foreach through all the array keys:
class Task
{
...
public function addIssue($issue)
{
return $this->issues()->create($issue);
}
}
Controller logic can be simplified, and this is a good opportunity to do some server-side validation:
public function store(Request $request, Task $task)
{
$attributes = request()->validate([
// issue validation rules here
]);
$task->addIssue($attributes);
return back();
}
You could try adding hidden field to your form where you should set value of that field to task_id which then will be passed to Controller when you submit form.
I think after that your First method should work properly.

Laravel 5.7 validate fields with asterisk, required_if

I have a Vue form that let users add work experience for there profile.
Users can add extra experience by clicking on a button. Clicking on that will add an new item with new input fields. I can't add the whole script because it's quit big. But here is an example to give you an idea:
<div class="item">
<div class="row">
<div class="form-group col-md-6">
<label class="form-label">Title</label>
<input type="text" name="experiences[0][title]" class="form-control">
</div>
<div class="form-group col-md-6">
<label class="form-label">Institution</label>
<input type="text" name="experiences[0][institution]" class="form-control">
</div>
</div>
<div class="row">
<div class="col-md-12">
<textarea name="experiences[0][comments]" class="form-control"></textarea>
</div>
</div>
</div>
<div class="item">
<div class="row">
<div class="form-group col-md-6">
<label class="form-label">Title </label>
<input type="text" name="experiences[1][title]" class="form-control">
</div>
<div class="form-group col-md-6">
<label class="form-label">institution </label>
<input type="text" name="experiences[1][institution]" class="form-control">
</div>
</div>
<div class="row">
<div class="col-md-12">
<textarea name="experiences[1][comments]" class="form-control"></textarea>
</div>
</div>
</div>
After each element there is a button to add a new row. This works fine but I have some validation issues.
I only want to validate the fields if one of the fields has a value. For example:
If experiences[0][institution] has a value, experiences[0][title] and experiences[0][comments] are required.
This has to work in every order. If title has a value, the other fields are required.
I can't really find out a way how to validate this. This is my validation rule:
$this->validate(request(), [
'experiences.*.title' => 'required_if:experiences.*.institution,null',
'experiences.*.institution' => 'required_if:experiences.*.title,null',
]);
Problem here is that it simply doesn't validate. I can't figure out how to make a rule that says, if field X has a value, Y and Z are required.
Hope anyone here can help me finding a solution! :)
Like Azeame said, make a custom validation rule and check if all values are filled or all are empty. Something in de lines of:
public function passes($attribute, $value)
{
$required = ['title','institution','comments'];
$experience = collect($value)->reject(function ($item, $key) {
return empty($item);
});
if (count($experience) == 0) {
return true;
}
foreach ($required as $field) {
if ( !$experience->has($field)) {
return false;
}
}
return true;
}
Maybe there is a beter way, but this should work.
required_if doesn't work with null as it will treat it as a string ("null"), it will work with boolean values though.
Instead you can use the required_without rule:
$this->validate(request(), [
"experiences.*.title" => "required_without:experiences.*.institution",
"experiences.*.institution" => "required_without:experiences.*.title",
]);
Example
$experiences = [
[
"title" => "My title",
"institution" => "",
"comments" => "<p>My first description</p>", //passes
],
[
"title" => "",
"institution" => "My title",
"comments" => "<p>My second description</p>", //passes
],
[
"title" => "My title",
"institution" => "My title",
"comments" => "<p>My third description</p>", //passes
],
[
"title" => "",
"institution" => null,
"comments" => "<p>My forth description</p>", //fails
],
];
$rules = [
"experiences.*.title" => "required_without:experiences.*.institution",
"experiences.*.institution" => "required_without:experiences.*.title",
];
$validator = Validator::make(compact('experiences'), $rules);
dd($validator->fails());
Write a custom rule with php artisan make:rule and in the passes() function write a check to ensure that all of the array keys are present and also that at least 2 of the array values are not null. I'm thinking something like this:
function passes($attribute, $value){
if(array_keys($value) !== ['title','institution','comments']){
return false;
}
if(empty($value['title']) && empty($value['institution'])){
return false;
}
return true;
}
and in your $this->validate pass the rule as ['experiences.*' =>['array', new CustomRule()] instead of required_if...
I haven't checked this so feel free to edit if it's broken.

Form array validation Laravel 5.2

I am currently stuck on solving this problem. I am new to Laravel and the MVC framework. I am struggling to create the dynamic form that gives the user the ability to add as many forms as possible. When the user enters the page at first it generates 5 form fields . Here is a look at my code so far.
<div id ={{$id = "from".$i}} >
<div class="form-group col-md-6">
<div class="col-md-6 form-group">
<label for={{$id = "Address".$i}}>Address</label>
<input type="text" name = "address[{{$i}}]" class="form-control" id={{$id = "Address".$i}} placeholder="Street Address"> <!-- problem form array how does this work in laravel -->
</div>
<div class="form-group col-md-6">
<label for={{$id = "city".$i}}>City</label>
<input type="text" value = "{{ old('city') }}" class="form-control" id={{$id = "City".$i}} placeholder="City">
#if ($errors->has('city'))
<span class="help-block">
<strong>{{ $errors->first('city') }}</strong>
</span>
#endif
</div>
How would I go about validating a form in Laravel 5.2 with from array
here's my controller
public function Postdata(Request $request) {
$this->validate($request->all(), [
'address.*' => 'required|string',
'city' => 'required',
]);
}
I am using a for loop to generate the forms dynamically.
here is the error I get
ErrorException in ValidatesRequests.php line 49:
Argument 1 passed to App\Http\Controllers\Controller::validate() must be an instance of Illuminate\Http\Request, array given, called in
C:\wamp\www\Dynamic- 1.0\app\Http\Controllers\propContoller.php on line 34 and defined
Can someone please help or point me in the right direction thank you !
add name="city[{{$i}}]"
Create a specific request with php artisan make:request PostRequest
Change public function Postdata(Request $request) { to public function Postdata(PostRequest $request) {
Remove the validate function call from your controller
Go to /app/Http/Requests/PostRequest.php
Then edit the rules function to something like this ...
.
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
$rules = [];
foreach($this->request->get() as $key => $val)
{
$rules['address.' . $key] = 'required';
$rules['city.' . $key] = 'required';
}
return $rules;
}
Thank You man ! this is the solution I end up with
<div class="form-group col-md-6">
<div class="col-md-6 form-group">
<label for={{$id = "Address".$i}}>Address</label>
<input type="text" name="address[{{$i}}]" class="form-control" id={{$id = "Address".$i}} placeholder="Street Address">
</div>
in post request i did this
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules() {
$rules = [];
foreach($this->request->get('address') as $key => $val) {
$rules['address.'.$key] = 'required';
}
return $rules;
}

Categories