【问题标题】:Update method in laravel are going to create a new model in databaselaravel 中的更新方法将在数据库中创建一个新模型
【发布时间】:2020-03-22 08:55:53
【问题描述】:

我在 laravel restful api 构建中遇到问题,

我有以下控制器

 <?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);
}
}

和 route/api.php 如下:

Route::resource('kittrans','Kittrans\KittransController',['except'=>['index']]);

当我请求更新数据库中的对象时,问题是一个新模型将使用 $kittrans->save() 方法插入到表中!!

为什么会出现这个问题?

我的邮递员要求如下:

网址:myApp.test/kittrans/5003

方法:放置,补丁

内容类型:application/x-www-form-urlencoded

数据:item_id,kmo_id,count

我也添加了 dd($kittrans); 在 save() 方法之前,我得到了以下信息:

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 => "*"
]
}

为什么保存方法要在数据库中创建一个新的模型实例? 我已经在所有其他控制器中实现了更新方法,一切正常,但是对于这个控制器,我不明白问题出在哪里?

【问题讨论】:

  • 如果你在update() 函数中执行dd($kittrans);,你会得到什么? (将其添加到您的问题中,不要将其发布在 cmets 中)。 $kittrans 很可能不是现有记录的实例,而是一个实例,这意味着 save() 将保存一条新记录。我已经看到路由模型绑定的这个问题,但我不确定你会如何解决它。
  • 嗨@TimLewis dd($kittrans) 在保存方法之后?还是之前?
  • save() 方法之前;您需要在保存之前查看它是什么。
  • 是的,正如我所料,+exists: false 设置在Kittran 的那个实例上,这意味着它在数据库中不存在。以为我有解决方案,但没有;你的模型被命名为Kittrans,所以不是那个(虽然它应该是单数,Kittran)。我不确定这里发生了什么,因为我不使用模型绑定/注入,但这是核心问题。
  • 是的,名称 不应该 成为问题,只要它们匹配(在资源和实际模型名称中)。是的,我相信 5003 存在于数据库中,但 POSTing 到 myApp.test/kittrans/5003 没有正确地将 5003 转换为 Kittrans $kittrans;它应该返回一个带有id: 5003 的实例,如果找不到,它应该是一个 404。再说一次,我不能真正说出为什么会发生这种情况(抱歉),只是我可以看到出了什么问题.

标签: php laravel api


【解决方案1】:

模型绑定的控制器方法的参数命名不正确。

你的路由参数是kittran 不是kittrans;资源路由将使用资源的单数名称作为路由参数。您必须为绑定匹配该名称:

public function update(Request $request, Kittrans $kittran)

如果没有匹配,您只会获得一个新的模型实例注入,而不是发生模型绑定。

您可以运行route:list 命令来查看您的路线是如何定义的:

php artisan route:list

“Laravel 自动解析定义在路由或控制器操作中的 Eloquent 模型,其类型提示的变量名称与路由段名称匹配。” - Laravel 6.x Docs - Routing - Route Model Bindings - Implicit Binding

“默认情况下,Route::resource 将根据资源名称的“单一化”版本为您的资源路由创建路由参数。” - Laravel 6.x Docs - Controllers - Resource Controllers - Naming Resource Route Parameters

如果您想为该资源覆盖此行为,并使用kittrans 作为参数名称,您也可以这样做,那么您无需更改控制器方法的签名:

Route::resource('kittrans', 'Kittrans\KittransController', [
    'except'=> ['index'],
    'parameters' => ['kittrans' => 'kittrans'],
]);

【讨论】:

    【解决方案2】:

    我相信你的模型绑定不正确,当你的模型绑定错误时,Kittrans 对象将是空的并且不会保存到数据库中,当你填充并保存它时会保存一个新对象。要解决错误的模型绑定,请将其添加到 RouteServiceProvider.php

    use App\Kittrans;
    
    public function boot()
    {
        parent::boot();
    
        Route::model('kittrans', Kittrans::class);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-10-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多