Reputation: 119
I am facing a problem in laravel restful api building,
I have the following controller
<?php
namespace App\Http\Controllers\Kittrans;
use App\Http\Controllers\Controller;
use App\Inventory;
use App\Kittrans;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class KittransController extends Controller
{
public function index()
{
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$rules =[
'kmo_id' => 'required',
'item_id' => 'required|integer|min:1',
'store_id' => 'required|integer|min:1',
'count' => 'required|integer|min:1'
];
$this->validate($request,$rules);
// check if requested count of item less than or equal to count in store
$inventory = DB::table('inventories')->where(
[
['item_id','=',$request->input('item_id')],
['store_id','=',$request->input('store_id')]
]
)->get();
if($inventory->count()!=1)
{
return response()->json(['Error'=>'Model not found'],404);
}
$remaining = $inventory->get(0)->count;
if($request->input('count') > $remaining)
{
return response()->json(['Error'=>'Request item count should be less than in the selected store!'],422);
}
// get user id bu auth. but for now i will make it static to complete first version of api
testing
$request['user_id'] = 1;
$newModel = Kittrans::create($request->all());
$remaining = $remaining - $request->input('count');
Inventory::where('id',$inventory->get(0)->id)->update(array('count' => $remaining));
return response()->json($newModel,200);
}
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show(Kittrans $kittrans)
{
//
return response()->json($kittrans,200);
}
/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function edit($id)
{
//
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, Kittrans $kittrans)
{
$kittrans->fill($request->only([
'item_id',
'kmo_id',
'count'
]));
if($kittrans->isClean())
{
return response()->json(['Error'=>'You should make some changes in your values to update'],422);
}
$kittrans->save();
return response()->json($kittrans,200);
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy(Kittrans $kittrans)
{
//
$kittrans->delete();
return response()->json($kittrans,200);
}
}
and route/api.php as following :
Route::resource('kittrans','Kittrans\KittransController',['except'=>['index']]);
when i make a request to update the object in database the problem is a new model will be inserted into the table with $kittrans->save() method!!
why like this issue happening?
my request from postman look like this :
URL : myApp.test/kittrans/5003
method : put,patch
Content-type : application/x-www-form-urlencoded
data : item_id,kmo_id,count
Also i have added
dd($kittrans);
before save() method and i got the following :
Kittrans {#345
#fillable: array:4 [
0 => "count"
1 => "kmo_id"
2 => "item_id"
3 => "user_id"
]
#connection: null
#table: null
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: false
+wasRecentlyCreated: false
#attributes: array:3 [
"item_id" => "1"
"kmo_id" => "1"
"count" => "7"
]
#original: []
#changes: []
#casts: []
#dates: []
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: []
#touches: []
+timestamps: true
#hidden: []
#visible: []
#guarded: array:1 [
0 => "*"
]
}
why save method are going to create a new instance of model in db? i have implement update method in all other controllers and everything is ok, but for this controller i don't understand where is the problem?
Upvotes: 3
Views: 2176
Reputation: 50511
The parameter for your controller method for the model binding isn't named correctly.
Your route parameter is kittran
not kittrans
; resource routing will use the singular name of the resource for the route parameter. You have to match that name for the binding:
public function update(Request $request, Kittrans $kittran)
Without that match you are just getting a new model instance injected instead of a model binding happening.
You can run the route:list
command to see how your routes are being defined:
php artisan route:list
"Laravel automatically resolves Eloquent models defined in routes or controller actions whose type-hinted variable names match a route segment name." - Laravel 6.x Docs - Routing - Route Model Bindings - Implicit Binding
"By default,
Route::resource
will create the route parameters for your resource routes based on the "singularized" version of the resource name." - Laravel 6.x Docs - Controllers - Resource Controllers - Naming Resource Route Parameters
If you want to override this behavior, for this resource, and use kittrans
as the parameter name you can also do that, then you wouldn't need to change your controller method's signature:
Route::resource('kittrans', 'Kittrans\KittransController', [
'except'=> ['index'],
'parameters' => ['kittrans' => 'kittrans'],
]);
Upvotes: 2
Reputation: 18936
I believe you model binding is not correct, when you model binding is wrong the Kittrans object will be empty and not saved to the db, when you fill and save it will save a new object. To solve your wrong model binding add this to the RouteServiceProvider.php
.
use App\Kittrans;
public function boot()
{
parent::boot();
Route::model('kittrans', Kittrans::class);
}
Upvotes: 0