How to sync pivot with extra field in Laravel? - php

I need some help about a problem in Laravel . I have 3 tables:
pellets
specie (there are the trees)
specie_pellet (this is the pivot table)
The specie_pellet table is a pivot for the composition of a pellet and has an extra field called percentuale (percentage).
Obviously the relation is belongsToMany in Specie Class and belongsToMany in Pellet Class
In detail Pellet Class:
// Imposto la relazione con le Specie
public function specie()
{
return $this->belongsToMany(Specie::class)->withPivot('percentuale');
}
In detail Specie Class:
// Imposto la relazione con i Pellets
public function pellets()
{
return $this->belongsToMany(Pellet::class)->withPivot('percentuale');
}
To modify the table i use a form:
{!! Form::model($pellet, ['method' => 'PUT', 'route' => ['composizione.update', $pellet->id]]) !!}
<table class="table table-bordered">
<thead>
<th>Specie</th>
<th>Percentuale</th>
<th>Azione</th>
</thead>
<tbody>
#foreach($pellet->specie as $specie)
<tr>
<td>{!! Form::select('specie[]', $listaSpecie, $specie->id, ['class' => 'form-control']) !!}</td>
<td>
<input type="text" class="form-control" name="percentuale[]" value="{{ $specie->pivot->percentuale }}">
</td>
<td><a class="btn btn-danger" href="{{ url('composizione/pellet/elimina/id/' . $pellet->id . '/specie/' . $specie->id) }}">Elimina</a> </td>
</tr>
#endforeach
</tbody>
</table>
{!! Form::submit('Aggiorna Composizione', ['class' => 'btn btn-success']) !!}
{!! Form::close() !!}
the request pass to the route
Route::put('composizione/pellet/update/{id}', 'PelletController#updateComposizione')->name('composizione.update');
And finally I have the controller
public function updateComposizione(\App\Http\Requests\ComposizioneUpdateRequest $request, $id)
{
$pellet = Pellet::find($id);
$specie = Input::get('specie');
$percentuali = Input::get('percentuale');
$pellet->specie()->sync([$specie => ['percentuale' => $percentuali]]);
return redirect('admin/pellets/')->with('ok_success', 'Composizione aggiornata correttamente');
}
But I get this error: Illegal offset type
in PelletController.php line 94
at HandleExceptions->handleError(2, 'Illegal offset type', '/srv/users/serverpilot/apps/laraweb/app/Http/Controllers/PelletController.php', 94, array('request' => object(ComposizioneUpdateRequest), 'id' => '5', 'pellet' => object(Pellet), 'specie' => array('1', '7'), 'percentuali' => array('50', '50'))) in PelletController.php line 94
at PelletController->updateComposizione(object(ComposizioneUpdateRequest), '5')
at call_user_func_array(array(object(PelletController), 'updateComposizione'), array(object(ComposizioneUpdateRequest), 'id' => '5')) in Controller.php line 55
...
Can someone help me understand this please?
Thanks a lot and sorry for my english. I'm Italian ;)

I would suggest you review the laravel tutorials on forms and rethink this approach, namely the select may not be the best way to do this. The select is not the best way to solve this one.
Try doing this:
#foreach($pellet->specie as $specie)
{!! Form::open(["url" => "composizione/pellet/update/".$pellet->id, "method" => "PUT"]) !!}
<tr>
<td>
<input type="hidden" name="specie" value={{$specie->id}} />
<input type="text" class="form-control" name="percentuale" value="{{ $specie->pivot->percentuale }}">
</td>
<td><inpyt type="submit" class="btn btn-danger">Elimina</a> </td>
</tr>
{!! Form::close() !}}
#endforeach
The rest would probably work. What's happening here is you're going to update a single specie / percentuale combination at once, not multiple ones.

Related

How to incremented in table on button click laravel

I have Home.blade.php in which if I click vote button it should increment the count in candidate table.
home.blade.php
#foreach ($file as $show)
<div class="col-md-3" style="margin-bottom: 20px;">
<div class="card">
<img src="{{$show->image}}" style="width:100%">
<div class="card-body">
<h5 class="title">President</h5>
<p class="card-text">Name : {{$show->name}}</p>
<button>VOTE</button>
</div>
</div>
</div>
#endforeach
homecontroller
public function Count(){
DB::table('candidate')->increment('count');
return view('/home')->with('success', 'voted');
}
Route
Route::get('/home','Homecontroller#Count');
Please help me to increment the count, if not this method is there any other method to do the same.
Yes, there is a better way.
Add this to Your web.php
Route::put('/votesUp/{vote}', 'HomeController#upVote')->name('votes.upVote');
Route::put('/votesDown/{vote}', 'HomeController#downVote')->name('votes.downVote');
in your view list thats is index.blade.php add this two buttons
FORM BUILDER WAY
#foreach($candidates as $item)
<tr>
<td>{{ $loop->iteration }}</td>
<td>{!! $item->name !!}</td>
<td>{!! Form::model($item, ['method' => 'PUT', 'route' => ['votes.upVote', $item->id ] ,'enctype'=>'multipart/form-data' ]) !!}
{!! Form::submit( 'Up Vote', ['class' => '', 'name' => 'submitbutton', 'value' => 'upvote'])!!}
{!! Form::close() !!}</td>
<td>{!! Form::model($item, ['method' => 'PUT', 'route' => ['votes.downVote', $item->id ] ,'enctype'=>'multipart/form-data' ]) !!}
{!! Form::submit( 'Down Vote', ['class' => '', 'name' => 'submitbutton', 'value' => 'upvote'])!!}
{!! Form::close() !!}</td>
</tr>
#endforeach
HTML WAY
#foreach($candidates as $item)
<tr>
<td>{{ $loop->iteration }}</td>
<td>{!! $item->name !!}</td>
<td>
<form method="post" action="{{ route('votes.upVote', $item->id) }}">
#method('PUT')
#csrf
<input class="" name="submitbutton" value="Up Vote" type="submit">
</form>
<form method="post" action="{{ route('votes.downVote', $item->id) }}">
#method('PUT')
#csrf
<input class="" name="submitbutton" value="Down Vote" type="submit">
</form>
</td>
</tr>
#endforeach
I am Considering Your model as Candidate so add this to HomeController
ELOQUENT way
public function upVote(Request $request, $id)
{
Candidate::find($id)->increment('votes_count', 1);
return redirect()->back();
}
public function downVote(Request $request, $id)
{
Candidate::find($id)->decrement('votes_count', 1);
return redirect()->back();
}
DB Facade Way
public function upVote(Request $request, $id)
{
\DB::table('candidates')->where('id','=',1)->increment('votes_count', 1);
return redirect()->back();
}
public function downVote(Request $request, $id)
{
\DB::table('candidates')->where('id','=',1)->decrement('votes_count', 1);
return redirect()->back();
}
Explained:
When You click on the upvote button filed votes_count in candidates table will be
incremented by 1
When You click on the downvote button filed votes_count in candidates table will be decremented by 1
EDIT FOR undefined variable candidate
Find this line
#foreach($candidates as $item)
And Replace with
#foreach ($file as $item)
FIX FOR
Class App\Http\Controllers\HomeController does not exist
From
Route::put('/votesUp/{vote}', 'HomeController#upVote')->name('votes.upVote');
Route::put('/votesDown/{vote}', 'HomeController#downVote')->name('votes.downVote');
TO
Route::put('/votesUp/{vote}', 'Homecontroller#upVote')->name('votes.upVote');
Route::put('/votesDown/{vote}', 'Homecontroller#downVote')->name('votes.downVote');
Your Controller Class
Homecontroller
but i have wrongly written as
HomeController
Make sure your column count is integer type in migration
And:
You are writing it in wrong way
<button>VOTE</button>
change it to
<button>VOTE</button>
The vote button should be like this:
<button>VOTE</button>
With the functionalities like Upvote and Downvote as answered nicely by #manojkiran-a above, I would also add throttling. Now a days it is easy to create a bot which will send upvote requests even when you are using csrf token.
I would add :
'middleware' => 'throttle:5'
Which will allow only 5 requests per minute per IP address. Not entirely preventing it but making it little harder.
Route::put('/votesUp/{vote}', 'Homecontroller#upVote')->middleware('throttle:5')->name('votes.upVote');
Route::put('/votesDown/{vote}', 'Homecontroller#downVote')->middleware('throttle:5')->name('votes.downVote');

Adding Data to the multiple column in laravel 5.7

Hi I am working on a project and I need to do some addition while working on a table.
like I have to fill the three fields and change the status to 2 using checkbox Array. I tried it all but with no luck. Kindly look into it and Let me know the changes I can Do.
My Model CustomerLoad.php is
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class CustomerLoad extends Model
{
protected $fillable = [
'driver_id',
'vehicle_id',
'company_id',
'customer_id',
'package_type',
'from',
'to',
'in_mile',
'weight',
'height',
'width',
'length',
'rate',
'duration_text',
'ticket_number',
'status_id'
];
public function status()
{
return $this->belongsTo('App\Status');
}
}
My Controller for creating the page is Like this
public function create()
{
$csloads = CustomerLoad::paginate(4);
$driver = Driver::pluck('name', 'id')->all();
$vehicle = Vehicle::pluck('vin', 'id')->all();
$company = Company::pluck('name', 'id')->all();
return view('customerload.create', compact('csloads', 'driver', 'vehicle', 'company'));
}
for storing it
public function updatecsloads(Request $request)
{
if(isset($request->update_all) && !empty($request->checkBoxArray)){
$csloads = CustomerLoad::findOrFail($request->checkBoxArray);
foreach($csloads as $csload){
$input = $request->all();
dd($input);
// $csload->update($input);
}
// return redirect()->back();
// } else {
// return redirect()->back();
}
}
My View is like
<div class="card">
<div class="card-header card-header-rose card-header-text">
<div class="card-ttle">
<h4 class="card-text">Allocate Loads</h4>
</div>
</div>
<div class="card-body">
{!! Form::model(['method' => 'PATCH', 'action' => ['CustomerLoadsController#updatecsloads']]) !!}
<div class='form-group'>
{!! Form::select('checkBoxArray', ['' => 'Allocate'], null, ['class' => 'selectpicker form-control', 'data-style'=>'btn btn-link', 'id'=>''])!!}
</div>
<div class='form-group'>
{!! Form::submit('Allocate Loads', ['class'=>'btn btn-rose pull-right']) !!}
</div>
#if(count($csloads) > 0)
<div class="table-responsive">
<table class="table">
<thead>
<tr>
<th>ID</th>
<th><input type="checkbox" id="options"></th>
<th>Driver Name</th>
<th>Company Name</th>
<th>Vehicle Vin Number</th>
<th>Origin</th>
<th>Destination</th>
<th>Package Type</th>
<th>Dimensions</th>
<th>Weight</th>
</tr>
</thead>
<tbody>
#foreach($csloads as $csload)
#if($csload->status_id == 1)
<tr>
<td>{‌{$csload->id}}</td>
<td><input class="checkBoxes" type="checkbox" name="checkBoxArray[]" value="{‌{$csload->status ? $csload->status->id == 2 : $csload->status->id == 1}}"></td>
<td>{!! Form::select('driver_id', ['' => 'Choose Driver Name'] + $driver, null, ['class' => 'selectpicker form-control', 'data-style'=>'btn btn-link', 'id'=>'exampleFormControlSelect1'])!!}</td>
<td>{!! Form::select('company_id', ['' => 'Choose Company Name'] + $company, null, ['class' => 'selectpicker form-control', 'data-style'=>'btn btn-link', 'id'=>'exampleFormControlSelect1'])!!}</td>
<td>{!! Form::select('vehicle_id', ['' => 'Choose Vehicle Vin Number'] + $vehicle, null, ['class' => 'selectpicker form-control', 'data-style'=>'btn btn-link', 'id'=>'exampleFormControlSelect1'])!!}</td>
<td>{‌{$csload->from}}</td>
<td>{‌{$csload->to}}</td>
<td>{‌{$csload->package_type}}</td>
<td>{‌{$csload->length}}x{‌{$csload->width}}x{‌{$csload->height}}</td>
<td>{‌{$csload->weight}}</td>
</tr>
#endif
#endforeach
</tbody>
</table>
</div>
#else
<h1 class="text-center">No Loads Found</h1>
#endif
{!! Form::close() !!}
</div>
</div>
</div>
I am struck in the project kindly answer the question as soon as you can I shall be really obliged.
Thanks in advance
From Munish Rana
Love your Work
change 'method' => 'PATCH' to 'POST'
and add {{ method_field('PATCH') }} to form field like this
<form method="POST" action="your url" >
{{csrf_field()}}
{{ method_field('PATCH') }}
</form>

Updating multiple records using Laravel 5.3 model binding

I am pulling multiple records from MySQL and looping through model binding and filling all the input fields with some data.
Now, I may change 2 or 10 or all 26 fields and hit update button. I want to update all the records. Now, I don't know how $id works here? usually I update single record and I have $id which I can find and update only that field.
But that's not the case here. I am pulling 13 records(or 26 fields). 13 field_1 and 13 field_2. How to update all?
mycode
Database
Table
-id
-name
-field1 (updating this one)
-field2 (updating this one)
Routes
Route::get('/cat' , 'AdminController#cat');
Route::patch('/cat/{$id}/update','AdminController#cat_update');
Controller
public function cat(){
$cattfs = Catf::all();
return view('/cat',compact('cattfs'));
}
public function cat_update(Request $request, $id) // id = 1
{
$rules = array(
'field1' => 'required',
'field2' => 'required'
);
$validator = Validator::make(Input::all(), $rules);
if ($validator->fails()) {
return Redirect()->back()->withErrors($validator);
} else {
$cat = Cattf::find($id); //This wont work :/
$cat ->field1 = Input::get('field1');
$cat ->field2 = Input::get('field2');
$cat ->save();
return redirect('/cat');
}
}
Views
<div class="col-md-6" style="background-color:#fff">
<table class="table table-hover">
<thead>
<tr>
<th style="text-align: center">Product</th>
<th style="text-align: center">Pr</th>
<th style="text-align: center">Co</th>
</tr>
</thead>
<tbody>
#foreach ($cattos as $catto)
{!! Form::model($catto,[ 'method' =>'PATCH', 'url' => ['/cat/.$catto->id./update']]) !!}
<tr>
<td>{{$catto->name}}</td>
<td> {!! Form::text('field1' ,null , ['class'=>'form-control']) !!}</td>
<td> {!! Form::text('field2' ,null , ['class'=>'form-control']) !!}</td>
</tr>
#endforeach
<td colspan="3">
{!! Form::submit('UPDATE', ['class'=>'btn btn-primary btn-block']) !!}
{!! Form::close() !!}
</td>
</tr>
</tbody>
</table>
</div>
snapshot of the form
I don't think you can do this with Model binding (correct me if I'm wrong someone).
What you can instead do is generate an array of data to post to your controller.
For example:
{!! Form::open(['route' => 'catupdate']) !!}
#foreach ($cattos as $catto)
<tr>
<td>{{$catto->name}}</td>
<td>{!! Form::text('categories['.$catto->id.'][field1]', null, ['class'=>'form-control']) !!}</td>
<td>{!! Form::text('categories['.$catto->id.'][field2]', null, ['class'=>'form-control']) !!}</td>
</tr>
#endforeach
{!! Form::close() !!}
You should then receive an array in your controller, which you can loop around and update each record.
public function catupdate()
{
$categories = request()->input('categories');
foreach($categories as $id => $values) {
$cat = Cattf::find($id);
$cat->field1 = $values['field1'];
$cat->field2 = $values['field2'];
$cat->save();
}
}
You can then also validate the array by doing the following in your Request file
public function rules()
{
return [
'categories.*.field1' => 'required',
'categories.*.field2' => 'required'
];
}
this is untested and is an example demonstrating the concept

Laravel Form Model binding with dynamic table rows and auto fill from db

Laravel 5.2
My create form has the ability to dynamically add tr rows via jquery to insert more data into db. How do I pull this data and auto fill my edit form using Form Model Binding (or another way).
UPDATE due to Nazmul Hasan comment:
Code Examples:
View: (Supplier hasmany relationship with supplier extras)
#foreach ($supplier['SupplierExtra'] as $extra)
<tr class="master">
<td>{!! Form::text('SupplierExtraName[]', $extra->name, ['class' => 'form-control']) !!}</td>
<td>{!! Form::text('SupplierExtraCost[]', $extra->cost, ['class' => 'form-control']) !!}</td>
Controller:(store)
foreach ($request->get('SupplierExtraName') as $i => $row) {
if ($request->SupplierExtraName[$i] != null) {
Extra::create([
'supplier_id' => $supplier->id,
'name' => $request->SupplierExtraName[$i],
'cost' => $request->SupplierExtraCost[$i],
]);
}
}
Controller: (update) - UNKNOWN code
How do I tell Laravel which row to update in the db?
So following from Nazmul Hasan comment I have the following store function in my controller
Update Controller:
foreach ($request->get('SupplierExtraName') as $key => $row) {
Extra::where('id', $key)->update([
'name' => $request->SupplierExtraName[$key],
'cost' => $request->SupplierExtraCost[$key],
]);
Updated view:
#foreach ($supplier['SupplierExtra'] as $extra)
<tr class="master">
<td>{!! Form::text("SupplierExtraName[$extra->id]", $extra->name, ['class' => 'form-control']) !!}</td>
<td>{!! Form::text("SupplierExtraCost[$extra->id]", $extra->cost, ['class' => 'form-control']) !!}</td>
<td></td>
<td>
<button type="button" class="btn btn-primary btn-md addRow">
<span class="glyphicon glyphicon-plus-sign"></span> Add a row
</button>
</td>
</tr>
#endforeach
From what I can understand with your questions, you can try these:
1 Considering you have create the Model firsthand, get all that Model.
If you have not created the model, you can try:
php artisan make:model Example
For the sake of example, let's call it Example model.
Here might be its data:
----------------------------------------
ID Name Age Phone
----------------------------------------
1 Sam 20 12345
2 Mia 23 11234
2 Pull out all the data from the controller first
public function functionName(Example $example){
//We try to filter based on what your id is, say, id = 1
//then we store that inside a variable
$example = App\Example::where('id', '=', $example->id)->get();
//Passing the data using compact
return view('yourview', compact('example'));
}
3 Filling the form with your data
You need to put your data in this step, using foreach loop and putting the value using 'value' attribute inside html tag.
<form>
#foreach($example as $e)
<div class="input-group">
<h2 class="input-group">Category's Name</h2>
<!-- the $e->Name is from the data we passed previously -->
<input type="text" class="form-control input-lg" name="Name" value="{{ $e->Name }}">
</div>
#endforeach
</form>
Guess what will fill the text-input? That will be Sam.
The 'value' attribute inside the text-input is what you're looking far, as far as I understand.

Laravel 5 How to Pass 2 Models to a Form

I have form and i am using form model binding. My form is
{!! Form::model($vehicle,['url' => '/pages/store']) !!}
<table style="width:650px; margin-left: 4px;" >
<tbody>
<tr>
<td>ID</td>
<td>Model</td>
<td>Brand</td>
<td>License Plate</td>
</tr>
<tr>
<td>{!! Form::text('id' ,null , ['readonly'], ['class' =>'textboxlong form-control', 'style'=>'height:23px;']) !!}</td>
<td>{!! Form::text('model' ,null ,['class' =>'textboxlong form-control', 'style'=>'height:23px;']) !!}</td>
<td>
{!! Form::select('brand_id', $brands, null, ['id'=>'brandBox', 'style' => 'width:150px;']) !!}
</td>
<td>{!! Form::text('licenseplate' ,null ,['class' =>'textboxlong form-control', 'style'=>'height:23px;']) !!}</td>
</tr>
<tr>
<td colspan="2">Client</td>
</tr>
<tr>
<td colspan="2">{!! Form::select('representive_client_id', $clients, null, ['id'=>'clientSelectBox', 'class' => 'selectbox']) !!}</td>
</tr>
<tr>
<td colspan="2">Telephone Number</td>
</tr>
<tr>
<td colspan="2">{!! Form::text('tel_number' ,null ,['class' =>'textboxlong form-control', 'style'=>'height:23px;']) !!}</td>
</tr>
<tr>
<td colspan="2">Adress</td>
<td colspan="2">{!! Form::textarea('address' ,null ,['class' =>'textboxlong form-control','style'=>'height:60px;']) !!}</td>
</tr>
</tbody>
</table>
<div id="buttoncontainer">
<a class="btn btn-default" href="{{ URL::to( 'pages/vehicleprocess/' . $first -> id ) }}"><<</a>
#if($previous)
<a class="btn btn-default" href="{{ URL::to( 'pages/vehicleprocess/' . $previous ) }}">PREVIOUS</a>
#endif
#if($next)
<a class="btn btn-default" href="{{ URL::to( 'pages/vehicleprocess/' . $next ) }}">NEXT</a>
#endif
<a class="btn btn-default" href="{{ URL::to( 'pages/vehicleprocess/' . $last -> id ) }}">>></a>
<a class="btn btn-default" id="add">EKLE</a>
{!! Form::submit('EDIT', array('class'=>'btn btn-primary')) !!}
{!! Form::submit('NEW RECORD', array('class'=>'btn btn-primary')) !!}
</div>
{!! Form::close() !!}
I am passing the $vehicle as
$vehicle = Vehicle::where('vehicles.id',$id)->join('clients', 'vehicles.representive_client_id', '=', 'clients.id')->first();
Store Function
$client = new Client;
$client -> full_name = $client_id;
$client -> tel_number = $tel_number;
$client -> mobile_number = $mobile_number;
$client -> save();
$last_client_id = $client -> id;
$input = Request::except('client_id');
$vehicle = Vehicle::create($input);
$u_vehicle = Vehicle::orderBy('created_at', 'desc')->first();
$u_vehicle -> update(array('client_id' => $last_client_id));
I am able to see all values of these fields in my view but when it comes to store a new record to my database i am getting this error
Column not found Unknown column 'tel_number'
Guess i need to pass 2 models (Vehicle and Client) to the form but not sure how to make it. Any help would be appreciated.
In short you need to pass your view a instance of Vehicle with Client - I know you're trying to do that with the join but I'm guessing that isn't the right way to do it. I set up a clean install with Laravel and it appears to work when you set up the relationship on the model.
I'm unsure what your relationships are so let's assume a Client has one Vehicle so the Vehicle belongs to the Client. So we can put your relationship in your Vehicle.php
public function client() {
return $this->belongsTo('App\Client'); // or whatever the namespace to your class is
}
See more here on defining relationships: http://laravel.com/docs/5.1/eloquent-relationships#defining-relationships
Then when you load the model in your view you can do this:
$vehicle = \App\Vehicle::with('client')->where('id', $id)->first();
The important part being: with('client')
Then any text fields with Client attributes should be populated with the existing data.
I hope that helps, if you need more help please let me know. I've got sample code of it working in a blank laravel project so I can throw that up on github if you need to see it.

Categories