concatenate id to laravel request inside controller - php

I am working with multiple select box with quantity beside it, now in my controller I will loop the select box and get the quantity of that select box, I think of concatenating the id of the selected value in selectbox to the request quantity
Blade:
<form>
#foreach($packages as $package)
<label>
<input type="checkbox" name="packages[]" value="{{ $package->id}}">
{{ $package->name }}
</label>
<input type="number" name="quantity_{{ $package->id }}">
#endforeach
</form>
Controller:
public function add(Request $request) {
foreach($request->packages[] as $package) {
echo $package->id .'<br>';
echo $quantity_of_this_package; // should get the quantity of that package
}
}
how to know the quantity of the selected package? is concatenating a good solution for that?

You could be using the array notation for the other input as well, but telling it what key to use:
type="number" name="quantity[{{ $package->id }}]"
Then on the server side:
foreach ($request->input('packages', []) as $id)) {
echo "Package ID: ". $id ."\n";
echo "Quantity: ". $request->input('quantity.'. $id) ."\n";
}

Related

Laravel 7 - How to insert multiple data to mysql database

I am trying to insert data into database. But i don't know how to insert multi select checkbox data into the mysql database.
Controller
public function create(Request $request)
{
try {
$id_student = $request->get('id_student');
$consecutive = DB::select('SELECT SUM(idRecord) FROM record GROUP BY idRecord');
$final_consecutive = sprintf("%04d", $consecutive);
foreach($request->select as $data)
{
Records::create($data);
}
return back()->with('success', 'Constancia creada correctamente');
} catch (\Illuminate\Database\QueryException $e) {
$message = $e->getMessage();
if (strpos($message, "Duplicate entry")) {
return back()->with('err', 'Esta constancia ya ha sido creada');
}
if (strpos($message, "1366 Incorrect integer value: '' for column 'idGrupo'")) {
return back()->with('err', 'Debe seleccionar un grupo para poder continuar');
}
return back()->with('err', $message);
}
}
View
#foreach ($group->students as $student)
<tr>
<td class="align-middle text-center">
<input class="form-control" type="text" name="nombre" value="{{$student->lastName}} {{$student->Names}}" disabled>
</td>
<td class="align-middle text-center">
<input class="form-control form-control-sm" type="text" name="grade" value="{{isset($student->pivot->grade)?$student->pivot->grade:''}}" placeholder="grade" disabled>
</td>
<form action="{{url('/Create/Records')}}" method="POST">
<input class="form-control form-control-sm" type="hidden" name="id_student" value="{{$student->id_student}}" >
<td class="align-middle text-center">
<input id="select" type="checkbox" name="select[]">
</td>
</tr>
#endforeach
</tbody>
</table>
<div class="d-flex justify-content-center">
<button type="submit" class="btn btn-sm btn-outline-success">Save</button>
</div>
What I tried to do was use a select checkbox and then in the Controller I passed it as an array in the foreach loop, but honestly I think I'm nowhere close to figuring it out... Other than that the consecutive is automatically generated and I don't know how to pass it to the array as well.
I get this error by the way:
Argument 1 passed to Illuminate\Database\Eloquent\Builder::create()
must be of the type array, string given
You should pass data to your Model like:
Records::create(['id_student' => $idStudent, 'consecutive' => $consecutive]);
Currently, you are giving like:
Records::create('string');
Which is not correct way to pass the data. That's why getting the error.
Create() take array as parameter.
When your foreach loop execute $data value 0 or 1 as string so that why error is given.
if you want to create in foreach loop then
foreach($request->select as $data)
{
Records::create(['field_name' => $data]);
}
by default multiple select checkbox will be converted to assoc array with name that ends with [] as its key for example your using so you can access it like:
$select = $_POST['select'];
then you can iterate through the values this is a plain php would suggest to use the laravel method as it offers more like security and filter this one is a simple and fast solution. But if you using an ajax submission you should always make sure that the parameter always ends with [] example you have a get request but still the same syntax applies to post method:
http://localhost?select[]=1&select[]=2
the same code will work as on top but for get request like this you will use:
$select = $_GET['select'];
haven't tried on laravel request object but I think the same conversion is being done when your using the Request instance you may try that as well just make sure you always end the parameter name with [] but if the name of all the checkbox is set to select it will just return a single string which the error means.

Update status in database using checkbox - Laravel

The project can have different statuses. With the checkbox, I am trying to switch the status of the project from requested (1) to accepted (2). If the checkbox is unchecked the status is 1, checked it's 2.
When I check the checkbox I got a 419 but this is normally related to the token but I added a #csfr field. Why is the status not changed in the database?
Thanks for any help.
index.blade.php (summary of all the projects)
#foreach ($projects as $project)
<tbody>
<tr>
<form action="/projects/plan" method="post" id="statusForm">
#csrf
<input name="id" type="hidden" value="{{$project->id}}">
<td>
<input type="hidden" value="{{$project->status}}" name="status">
<input {{isset($project['status']) && $project['status'] == '2' ? 'checked' : ''}}
value="{{$project->status}}" type="checkbox" name="status"
onchange="document.getElementById('statusForm').submit()"
>
</td>
</form>
<td>{{$project->applicant_name}}</td>
<td>{{$project->project_name}}</td>
<td>Project Details</td>
</tr>
</tbody>
#endforeach
Project.php (functions to update status)
const STATUS_requested = 1;
const STATUS_ACCEPTED = 2;
public function updateStatus( $status )
{
$this->update([
'status' => $status
]);
$this->refresh();
return $this;
}
public function projectAccept() {
return $this->updateStatus( self::STATUS_ACCEPTED );
}
ProjectsController.php (dd('hello') is not printed it seems like data is not sent to this resource)
public function plan(Request $request)
{
dd('hello');
Event::find($request->id)->projectAccept();
return Project::STATUS_ACCEPTED;
}
web.php
// Update status project
Route::post('/projects/plan', 'ProjectsController#plan');
First, you cant select by ID document.getElementById('statusForm').submit() when you have multiple DOMS with the same ID.
change your loop to something like this
#foreach ($projects as $project)
<tbody>
<tr>
<td>
<form action="/projects/plan" method="post" id="statusForm{{$project->id}}">
#csrf
<input name="id" type="hidden" value="{{$project->id}}">
<input {{isset($project['status']) && $project['status'] == '2' ? 'checked' : ''}}
value="2" type="checkbox" name="status"
onchange="document.getElementById('statusForm{{$project->id}}').submit()"
>
</form>
</td>
<td>{{$project->applicant_name}}</td>
<td>{{$project->project_name}}</td>
<td>Project Details</td>
</tr>
</tbody>
#endforeach
Now, a checkbox will only be sent in a form when it is checked, so no need for a variable value for that input
<input {{isset($project['status']) && $project['status'] == '2' ? 'checked' : ''}}
value="2" type="checkbox" name="status"
onchange="document.getElementById('statusForm{{$project->id}}').submit()"
>
Finally, when you recover the input status, set a default value for the unchecked one (you can remove the hidden input with this one). Or as you did, set a hidden input with the original value to be sent every time. Both solution are perfect.
public function plan(Request $request)
{
$status = $request->input('status', Project::STATUS_requested);
Event::find($request->id)->projectAccept();
return Project::STATUS_ACCEPTED;
}
That way if it is checked it will be 2 (in the request) and if not, it will be 1 from the default value.

how to save checkbox value in array form?

How to save multiple checkbox value into database? now the value is storing in different rows. example: i selected value 1 and 2.so the value 1 in 1 row and value 2 in another row.
blade
<form enctype="multipart/form-data" action="/report/{{$postqs->id}}"
method="POST">
<input type="checkbox" name="item[]" value="one" />1
<input type="checkbox" name="item[]" value="two" />2
<input type="checkbox" name="item[]" value="three" />3
<div class="row">
<div class="form-group">
<label class="control-label col-sm-2"> Others:</label>
<div class="col-sm-7">
<textarea name="report" id="report" class="form-control"></textarea>
</div>
</div>
<input type="hidden" name="_token" value="{{ csrf_token() }}">
<input type="submit" class="pull-right btn btn-sm btn-primary">
</div></div></div>
</form>
Report model
protected $fillable = ['report','postqs_id','user_id','item'];
Store controller :
public function store(Request $request,Postqs $postqs,$id,Report $report,
Admin_report $admin_report)
{
foreach ($request->input("item") as $key=>$value){
$add_item = new Report;
$add_item->item= $value;
$add_item->user_id= Auth::user()->id;
$add_item->postqs_id=$id;
$add_item->save();
return back();
}
You should separate items as key and value so that you can save the value and the error it gives you shows that it needs user_id, so add the user_id to it., and your code should look like this:
foreach ($request->input("item") as $key=>$value){
$add_item = new Report;
$add_item->item= $value;
$add_item->user_id= Auth::user()->id;
$add_item->postqs_id=$id;
$add_item->save();
}
Because you want the value of the checkboxes, not the key. In the way you do it, it saves key and value together in the item column.
#Update
In this situation (saving array into DB) you don't put item input into foreach loop, and just save it as what it is, before that you must tell to your model to treat that as an array by putting $casts property into Report model:
protected $casts = [
'items'=>'array',
];
This way it should save as array into items column. after that you just save items like this code below:
$add_item = new Report;
$add_item->item= $request->input("item");
$add_item->user_id= Auth::user()->id;
$add_item->postqs_id=$id;
$add_item->save();
Note that there is no need for foreach loop in this scenario.
It seems you need to add user_id to insert a new Report.
$user = auth()->user();
foreach ($request->input("item") as $item){
$add_item = new Report;
$add_item->user_id= $user->id;
$add_item->item= $item;
$add_item->save();
}

Why is my form only passing input data from last field within foreach loop to database?

I am trying to update some data in my database from a form with this foreach loop:
$players_ids = $_POST['player_ids'];
foreach($players_ids as $player_id) {
foreach($_POST['goals'] as $goals) {
var_dump($goals);
$updateGoals = \DB::table('stats')->where('id', $player_id)->update(['goals' => $goals]);
}
foreach($_POST['assists'] as $assists) {
var_dump($assists);
$updateAssists = \DB::table('stats')->where('id', $player_id)->update(['assists' => $assists]);
}
foreach($_POST['tackles'] as $tackles) {
var_dump($tackles);
$updateTackles = \DB::table('stats')->where('id', $player_id)->update(['tackles' => $tackles]);
}
}
Here is the form:
#foreach($players as $player)
<tr>
<input type="hidden" name="player_ids[]" value="{{ $player->id }}">
<input type="hidden" name="game_id" value="{{ $game->id }}">
<td>{{ $player->fn }} {{ $player->ln }}</td>
<td><input type="number" value="0" name="goals[]" placeholder="goals"></td>
<td><input type="number" value="0" name="assists[]" placeholder="assists"></td>
<td><input type="number" value="0" name="tackles[]" placeholder="tackles"></td>
</tr>
#endforeach
When I try to submit this data, instead of passing through the individual stats of each player to the database, it only passes through the data of the last player in the foreach loop to every player. So if the final player has 3 goals, everyone will get 3 goals in the database. This is obviously not how I would like this to function.
I know soon after this I will run into an issue with updating the data in my database, because I'm not looking to override what is already in the database, but instead add the value passed through to the value already in the database, so if anyone has any knowledge on that as well would be greatly appreciated.
Your form has multiple copies of elements with the same name. Due to this, it only uses the last element with that name.
To utilize an array of values, you will need to use [] like you did for player_ids.
The reason this is happening is you are updating each player with the very last value set for goals, assists, and tackles. (Actually you are updating each player with every set for goals, assists and tackles, resulting in many queries.) You might need to change up your inputs so you know exactly what to update each player with.
This will also result in less looping and fewer queries.
#foreach($players as $player)
<tr>
<input type="hidden" name="player_ids[]" value="{{ $player->id }}">
<input type="hidden" name="game_id" value="{{ $game->id }}">
<td>{{ $player->fn }} {{ $player->ln }}</td>
<td><input type="number" value="0" name="goals[{{ $player->id }}]" placeholder="goals"></td>
<td><input type="number" value="0" name="assists[{{ $player->id }}]" placeholder="assists"></td>
<td><input type="number" value="0" name="tackles[{{ $player->id }}]" placeholder="tackles"></td>
</tr>
#endforeach
$players_ids = $_POST['player_ids'];
foreach ($players_ids as $player_id) {
$updates = \DB::table('stats')->where('id', $player_id)->update([
'goals' => $_POST['goals'][$player_id],
'assists' => $_POST['assists'][$player_id],
'tackles' => $_POST['tackles'][$player_id]
]);
}
This is untested, but if you want it to be additive in your database and not overwrite past values, you might be able to do something like this...
$players_ids = $_POST['player_ids'];
foreach($players_ids as $player_id) {
$updates = \DB::table('stats')->where('id', $player_id)->update([
'goals' => $_POST['goals'][$player_id] . '+' . DB::raw('goals'),
'assists' => $_POST['assists'][$player_id] . '+' . DB::raw('assists'),
'tackles' => $_POST['tackles'][$player_id] . '+' . DB::raw('tackles')
]);
}
Generally a better route would be to not make them additive though, and then you'd just use sum() to figure out how many goals, tackles, and assists each player has. Then you'd be able to do additional filtering on that like goals by date, goals by game, etc...

Looping through input array in Laravel 5

I have a basic UI where users can add a simple list with a label and a value. I want to loop through that list to store the data in a "Detail" model.
I have the following code.
Controller:
$details = $request->input('detail_label');
foreach($details as $key => $value)
{
if(!empty($request->input('detail_value.'.$key))) {
// if the detail has an existing ID
if($request->input('detail_id.'.$key)) {
$detail = Detail::find($request->input('detail_id.'.$key));
} else {
$detail = new Detail;
}
$detail->type = $request->input('detail_type.'.$key);
$detail->label = $request->input('detail_label.'.$key);
$detail->value = $request->input('detail_value.'.$key);
if($request->input('detail_privacy.'.$key) == 1) {
$detail->privacy = 1;
} else {
$detail->privacy = 0;
}
$user->details()->save($detail);
}
}
View:
#foreach($user->details as $detail)
<div class="detail">
<input type="hidden" name="detail_id[]" value="{{ $detail->id }}">
<label>Type
<select name="detail_type[]">
<option #if($detail->type == '1')selected #endif value="1">Phone</option>
<option #if($detail->type == '2')selected #endif value="2">Phone (mobile)</option>
<option #if($detail->type == '3')selected #endif value="3">URL</option>
<option #if($detail->type == '4')selected #endif value="4">Email</option>
</select>
</label>
<label>Label
<input type="text" name="detail_label[]" value="{{ $detail->label }}">
</label>
<label>Value
<input type="text" name="detail_value[]" value="{{ $detail->value }}">
</label>
<label>Private?
<input type="checkbox" name="detail_privacy[]" #if($detail->privacy == true) checked #endif value="1">
</label>
<label>Delete?
<input type="checkbox" name="detail_delete[]" value="{{ $detail->id }}">
</label>
</div><!-- / detail -->
#endforeach
Every aspect of my code works as I had planned except the detail_privacy field. It sets and unsets the boolean privacy attribute but it pays no attention to which $key I want. It always sets it according to the order in the loop. If I just set one detail to be private it will be first. If I set two, (whichever two), it will be the first and second.
Something is clearly wrong with my logic but I can't tell what.
Any help would be really appreciated. Thanks!
The reason it doesn't work is that non-checked checkboxes are not included in the post data. You may see it by dumping value of $request->input('detail_privacy').
To be able both to edit existing and add new details, you need to set keys on inputs in the form. Anything really, as long as you keep track of it. To make things easier you can add hidden input named same as the checkbox, so detail_privacy will be always present in the post data. For example:
#foreach ($user->details as $key => $detail)
<input type="hidden" name="detail_id[{{ $key }}]" value="{{ $detail->id }}">
...
<input type="hidden" name="detail_privacy[{{ $key }}]" value="0">
<input type="checkbox" name="detail_privacy[{{ $key }}]" #if($detail->privacy == true) checked #endif value="1">
...
#endforeach
If you add new fields dynamically ie. with javascript you need to respect those keys. Its quite simple though, just pass last value of $key to your js and you're set.
Also I would recommend different notation for input names: details[{{ $key }}][id] instead of detail_id[{{ $key }}]. This way controller action will become much simpler:
foreach ($details as $detail) {
if (! empty($detail['id'])) {
...
}
}
If the Boolean values are stored as TINYINTS in the Database (as in: 0 or 1); then perhaps taking out the Boolean true || false may resolve the Issue. Not Certain but guessing it's worth the try:
<!-- JUST TRY IT LIKE SO: #if($detail->privacy) checked #endif -->
<label>Private?
<input type="checkbox"
name="detail_privacy[]"
#if($detail->privacy) checked #endif value="1"
>
</label>
Or Hypothetically:
<!-- YOU MAY ALSO USE "1" LIKE SO: #if($detail->privacy==1) checked #endif -->
<label>Private?
<input type="checkbox"
name="detail_privacy[]"
#if($detail->privacy==1) checked #endif value="1"
>
</label>

Categories