【问题标题】:Updating json column along with other columns in laravel更新 json 列以及 laravel 中的其他列
【发布时间】:2018-06-22 15:19:48
【问题描述】:

我想知道您如何更新 JSON 列数据,而其他列也需要更新。

当我在 laravel 网站上看到示例时,json 列是这样的

DB::table('users')
            ->where('id', 1)
            ->update(['options->enabled' => true]);

但是其他列呢?

这是我目前拥有的:

public function update(Request $request, $id)
    {
        $order = Order::find($id);
        $this->validate($request, array(
            'payment_id'=>'nullable',
            'orderstatus_id' => 'required|numeric',
            'address_id' => 'required|numeric',
        ));

        $order = Order::where('id',$id)->first();
        $order->payment_id = $request->input('payment_id');
        $order->orderstatus_id = $request->input('orderstatus_id');
        $order->address_id = $request->input('address_id');

        $order->save();

        return redirect()->route('orders.index',
            $order->id)->with('success',
            'Order updated successfully.');
    }

我有一个名为 product_name 的列,它是 Json 类型的列,其中我有下面这样的示例数据,例如,我想在其中编辑 quantity 的产品。

{"29": {"id": 29, "name": "effewf", "price": 24524, "quantity": 3, "attributes": [], "conditions": []}, "37": {"id": 37, "name": "test product", "price": 456346, "quantity": 2, "attributes": [], "conditions": []}}

正如您在此订单中看到的,我有 2 件产品,一件数量为 3,另一件数量为 2。

【问题讨论】:

    标签: php json laravel eloquent


    【解决方案1】:

    处理此问题的最佳方法是为此数据创建模型和表。

    但是如果你想使用JSON,你可以使用模型中的casts属性:

    protected $casts = [
        'product_name' => 'array',
    ];
    

    然后,您将能够像使用数组一样使用选项:

    $order = Order::where('id',$id)->first();
    $order->payment_id = $request->input('payment_id');
    $order->orderstatus_id = $request->input('orderstatus_id');
    $order->address_id = $request->input('address_id');
    $order->product_name[$request->product_id]['quantity'] = $request->new_product_quantity);
    $order->save();
    

    如果不想使用强制转换,可以手动转换数据:

    $order->product_name = json_encode(
        json_decode($order->product_name, true)[$request->some_product_id]['quantity'] = $request->new_quantity
    );
    

    【讨论】:

    • 当我使用json_decode 来获取我的数据时,如果我在我的模型中使用casts,我会得到json_decode() expects parameter 1 to be string, array given 的错误,但如果除了'product_name' => 'array', 我使用'product_name' => '', 我仍然可以得到没有错误的结果,使用empty 进行强制转换而不是数组会不会有问题?
    • @mafortis casts 将在保存到数据库之前自动将 JSON 转换为数组,然后将数组转换为 JSON。所以,你不需要使用json_decode() 或json_encode()
    • 不,你没有明白我的意思。问题是如果我在我的模型中添加该数组,我必须更改我所有的函数和刀片代码才能再次获得我目前得到的东西。那么只使用'' 而不是'array' 有问题吗?
    • @mafortis 如果您目前在任何地方都使用json_decode(),请不要使用casts 并手动执行此操作json_encode(json_decode($order->product_name), true)[$request->some_product_id]['quantity'] = $request->new_quantity)。但是使用casts 会好很多。
    • 好的,你介意用你刚才给我的答案编辑你的代码吗?如果你能解释这个$request->product_id和new_product_quantity来自哪里,请让我清楚吗?我在刀片中输入的名称应该是什么以进行验证?
    【解决方案2】:

    Laravel 文档中有一个关于 arrays and JSON 的部分。这样做的方法是将$casts 属性添加到您的Order 模型中:

    protected $casts = [
        'product_name' => 'array',
    ];
    

    在您的刀片视图和控制器中,您应该能够直接访问$order->product_name - 不再需要进行任何json_decode() 调用。

    更新特定值时,在您的“编辑顺序”视图中,您可能希望将表单输入命名为类似的名称,以便轻松映射您的更新,即类似于:

    @foreach($order->product_name as $data) 
        <label>Name:</label>
        <input
          type="text"
          name="product_name[{{ $data['id'] }}][name]"
          value="{{ $data['name'] }}"
        >
    
        <label>Price:</label>
        <input
          type="text"
          name="product_name[{{ $data['id'] }}][price]"
          value="{{ $data['price'] }}"
        >
    
        <label>Quantity:</label>
        <input
          type="number"
          name="product_name[{{ $data['id'] }}][quantity]"
          value="{{ $data['quantity'] }}"
        >
    @endforeach
    

    这意味着在控制器的update() 方法中,您可以像往常一样使用从请求输入中获取的新值。如果您想严格遵循文档中的格式,您还应该将其设置在一个新变量中,而不是直接设置它,即

    public function update(Request $request, $id)
    {
        $order = Order::find($id);
    
        // ... other usual stuff
    
        // get original data
        $new_product_name = $order->product_name;
    
        // contains all the inputs from the form as an array
        $input_product_name = $request->input('product_name');
        // loop over the product array
        foreach ($input_product_name as $data_id => $data) {
            // loop over each input for the product in the view form
            foreach ($data as $key => $value) {
                 // set the new value
                 $new_product_name[$data_id][$key] = $value;
            }
        }
        // set the new data (should automatically serialize into JSON for storage)
        $order->product_name = $new_product_name;
    
        $order->save();
    }
    

    【讨论】:

    • 上面的代码有效,但是当我保存数据时出现问题,除了更新值它会添加另一个,看看数量{"id": 29, "name": "effewf", "price": 24524, "quantity": 3, "'quantity'": "1", "attributes": [], "conditions": []}
    • @mafortis 错误地在输入名称中留下了单引号 - 在我的答案中删除了它们,现在应该可以工作了。如果您想确保价格和数量是整数值,您将需要使用type="number" 输入,或者不要对$data 进行循环,而是显式设置每个键,以便您可以int-cast需要。
    猜你喜欢
    • 2022-11-19
    • 1970-01-01
    • 2019-10-14
    • 2019-01-20
    • 1970-01-01
    • 1970-01-01
    • 2021-10-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多