侧边栏壁纸
博主头像
云BLOG 博主等级

行动起来,活在当下

  • 累计撰写 318 篇文章
  • 累计创建 6 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录
SQL

thinkphp8 接收到前端POST传来的数组, 将tabledata分开保存

Administrator
2025-03-14 / 0 评论 / 0 点赞 / 0 阅读 / 0 字

thinkphp8 接收到前端POST传来的数组, 将tabledata array:54 [ "py" => "" "type" => "A" "count" => "0" "counts" => "6" "card" => "" "name" => "" "phone" => "" "tel" => "" "address" => "" "zip" => "" "office" => "0" "email" => "" "date" => "2025-03-09" "age" => "" "yue" => "" "ri" => "" "sphericalr" => "" "cylindricalr" => "" "axialr" => "" "correctionr" => "1.0" "nakedr" => "" "prismr" => "" "basisr" => "" "addr" => "" "originallightr" => "" "pupilheightr" => "" "invisibler" => "" "sphericall" => "" "cylindricall" => "" "axiall" => "" "correctionl" => "1.0" "nakedl" => "" "prisml" => "" "basisl" => "" "addl" => "" "originallightl" => "" "pupilheightl" => "" "invisiblel" => "" "pupildistancer" => "" "pupildistancel" => "" "optometrist" => "" "cardamountdown" => "" "cardpointsdown" => "" "getglgdate" => "2025-03-09" "store" => "万福店" "stockid" => "02" "cashier" => "w800gl" "groupflag" => "A" "paytype" => "微信" "salesman" => "057" "details" => "" "totalamount" => "194.00" "pay" => "194.00" "tabledata" => "[{"stockname":"万福店","number":1,"goodsname":"A0112-00.00-0.00","type":"A","types":"镜片","brands":"暴龙光赞1.56非球面防蓝光-0.00","sph":null,"cyl":null,"addlight":null,"stockid":"02","unit":"片","sale":"194","buy":"30.5","buyave":"13.7164","total":"194","pay":"194","commission":"3.5"},{"stockname":"万福店","number":1,"goodsname":"A0156-00.00-0.00","type":"A","types":"镜片","brands":"卡蒂诺1.56非球面近视防蓝光-0.00","sph":null,"cyl":null,"addlight":null,"stockid":"02","unit":"片","sale":"0","buy":"9.5","buyave":"10.0748","total":"0","pay":"0","commission":"3.5"},{"stockname":"万福店","number":1,"goodsname":"A0094-00.00-0.001.50","type":"A","types":"镜片","brands":"卡蒂诺1.56渐进片-0.00下加:1.50 ","sph":null,"cyl":null,"addlight":null,"stockid":"02","unit":"片","sale":"0","buy":"48","buyave":"48","total":"0","pay":"0","commission":"3.5"},{"stockname":"万福店","number":1,"goodsname":"A0094-00.00-0.001.00","type":"A","types":"镜片","brands":"卡蒂诺1.56渐进片-0.00下加:1.00 ","sph":null,"cyl":null,"addlight":null,"stockid":"02","unit":"片","sale":"0","buy":"14","buyave":"14","total":"0","pay":"0","commission":"3.5"},{"stockname":"万福店","number":1,"goodsname":"A0184-00.00-0.00","type":"A","types":"镜片","brands":"卡蒂诺1.56非球面近视-0.00","sph":null,"cyl":null,"addlight":null,"stockid":"02","unit":"片","sale":"0","buy":"6","buyave":"6","total":"0","pay":"0","commission":"3.5"},{"stockname":"万福店","number":1,"goodsname":"A0094-00.00-0.002.00","type":"A","types":"镜片","brands":"卡蒂诺1.56渐进片-0.00下加:2.00 ","sph":null,"cyl":null,"addlight":null,"stockid":"02","unit":"片","sale":"0","buy":"47.5","buyave":"38.125","total":"0","pay":"0","commission":"3.5"}]" tabledata里面的一条条分开保存到MYSQL,同时把tabledata里面的number字段和另一个库存表number计算后写入库存表.其它数据保存到另一个表,给出完整代码和示例,并注释

已深度思考(用时 33 秒)

好的,我现在要解决的问题是在ThinkPHP 8中处理前端POST传来的数组数据,将tabledata中的每条记录分别保存到数据库,同时处理库存表的更新。我需要仔细分析需求,然后一步步思考如何实现。

首先,我需要理解用户的数据结构。用户传来的数据中有一个tabledata字段,里面是一个JSON数组,每个元素代表一条需要保存到数据库的记录。同时,每个记录中的number字段需要与另一个库存表进行计算,然后更新库存表的数量。其他数据可能需要保存到另一个表,比如订单主表。

接下来,我需要考虑如何接收和处理这些数据。在ThinkPHP 8中,控制器通常用来处理请求数据。首先,从请求中获取tabledata字段,并将其从JSON字符串转换为PHP数组。然后,遍历这个数组,逐条保存到对应的数据库表中。这里可能需要使用事务来确保数据的一致性,特别是在处理库存更新时,避免出现部分成功的情况。

然后是库存表的处理。假设库存表中有一个字段记录商品的数量,当接收到tabledata中的number时,需要根据商品信息(如goodsname或stockid)查找对应的库存记录,并将现有的数量减去或加上传入的number。这里需要确认number的含义,比如是销售数量,那么库存应该减少这个数值。如果是入库,则增加。根据用户给出的示例数据,例如"number":1,可能表示销售了一件商品,因此库存应减少1。

另外,用户提到其他数据需要保存到另一个表,比如订单主表。主表可能包含订单的总体信息,如总金额、支付方式、销售员等,而tabledata中的每个条目则是订单明细,需要保存到订单明细表。因此,可能需要先创建主订单记录,获取订单ID,然后将明细记录与订单ID关联。

接下来,我需要考虑代码的结构。在控制器中,首先接收并验证数据,然后开启数据库事务。处理主表数据,保存到主表,获取自增ID。然后处理tabledata的每个条目,保存到明细表,并同时更新库存表。如果在过程中出现任何错误,事务回滚,返回错误信息;否则提交事务,返回成功。

代码中需要注意的几点:

1. 使用Request对象获取POST数据。

2. JSON解码tabledata时,确保正确处理,可能需要进行验证。

3. 使用Db类或模型进行数据库操作。

4. 处理库存更新时,要确保原子性,可能使用update加setDec或setInc方法,或者直接写SQL语句。

5. 事务的管理,确保所有操作都成功才提交。

可能的错误点:

- tabledata字段可能未正确解析,导致无法获取数组。

- 库存更新时,未找到对应的商品,导致更新失败。

- 未处理并发情况下的库存更新,可能导致数据不一致。不过,在事务中处理,结合行锁,可以缓解这个问题。

现在,我需要编写具体的代码示例,包括注释,说明每一步的操作。例如:

1. 在控制器中处理POST请求。

2. 获取并验证必要字段。

3. 解码tabledata为数组。

4. 开启事务。

5. 保存主表数据,获取主表ID。

6. 遍历tabledata,保存明细表,并更新库存。

7. 提交事务或回滚。

同时,需要给出模型或数据库表的示例结构,比如主表order和明细表order_detail,库存表stock的结构。

例如,主表可能包含totalamount、pay、store等字段,而明细表包含goodsname、number、sale等字段,库存表包含stockid、goodsname、quantity等字段。

在代码中,使用Db::name('order')插入主表数据,然后获取lastInsertId。接着循环处理每个明细项,插入到order_detail,并更新stock表的quantity字段,减去number的值。

需要注意的是,库存更新可能需要根据goodsname和stockid来唯一确定一个商品,因此需要确保查询条件正确。

此外,处理过程中需要捕获异常,如数据库操作失败,此时回滚事务,并返回错误信息。

最后,给出完整的代码示例,包括必要的注释,说明每个步骤的作用,以及如何处理数据和更新库存。

以下是基于ThinkPHP 8的完整代码示例,包含注释说明:

php

复制

<?php
namespace app\controller;

use think\facade\Db;
use think\facade\Request;
use think\Response;

class OrderController
{
    public function saveOrder()
    {
        // 获取POST数据
        $postData = Request::post();

        // 验证必要字段是否存在
        if (!isset($postData['tabledata'])) {
            return json(['code' => 400, 'msg' => '缺少tabledata参数']);
        }

        // 解析JSON数据
        try {
            $tableData = json_decode($postData['tabledata'], true, 512, JSON_THROW_ON_ERROR);
        } catch (\JsonException $e) {
            return json(['code' => 400, 'msg' => 'tabledata格式错误']);
        }

        // 开启事务
        Db::startTrans();

        try {
            // 保存主表数据(示例表名:order)
            $mainOrderData = [
                'totalamount' => $postData['totalamount'] ?? 0,
                'pay'         => $postData['pay'] ?? 0,
                'store'       => $postData['store'] ?? '',
                'paytype'     => $postData['paytype'] ?? '',
                'salesman'    => $postData['salesman'] ?? '',
                'created_at'  => date('Y-m-d H:i:s')
            ];

            $orderId = Db::name('order')->insertGetId($mainOrderData);

            // 处理明细数据
            foreach ($tableData as $item) {
                // 保存明细表(示例表名:order_detail)
                $detailData = [
                    'order_id'    => $orderId,
                    'goodsname'   => $item['goodsname'] ?? '',
                    'number'      => $item['number'] ?? 0,
                    'sale'        => $item['sale'] ?? 0,
                    'stockid'     => $item['stockid'] ?? '',
                    'unit'        => $item['unit'] ?? '',
                    // 其他字段...
                ];
                Db::name('order_detail')->insert($detailData);

                // 更新库存(示例表名:stock)
                // 根据商品唯一标识(这里用goodsname + stockid组合)更新库存
                Db::name('stock')
                    ->where('goodsname', $item['goodsname'])
                    ->where('stockid', $item['stockid'])
                    ->dec('quantity', $item['number']) // 减少库存
                    ->update();
            }

            // 提交事务
            Db::commit();
            return json(['code' => 200, 'msg' => '操作成功', 'order_id' => $orderId]);

        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            return json(['code' => 500, 'msg' => '操作失败:' . $e->getMessage()]);
        }
    }
}

数据库表示例结构

  1. 主订单表 (order)

sql

复制

CREATE TABLE `order` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `totalamount` decimal(10,2) DEFAULT 0.00,
  `pay` decimal(10,2) DEFAULT 0.00,
  `store` varchar(255) DEFAULT '',
  `paytype` varchar(50) DEFAULT '',
  `salesman` varchar(50) DEFAULT '',
  `created_at` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
);
  1. 订单明细表 (order_detail)

sql

复制

CREATE TABLE `order_detail` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `order_id` int(11) NOT NULL,
  `goodsname` varchar(255) NOT NULL,
  `number` int(11) DEFAULT 0,
  `sale` decimal(10,2) DEFAULT 0.00,
  `stockid` varchar(50) DEFAULT '',
  `unit` varchar(20) DEFAULT '',
  PRIMARY KEY (`id`)
);
  1. 库存表 (stock)

sql

复制

CREATE TABLE `stock` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `goodsname` varchar(255) NOT NULL,
  `stockid` varchar(50) NOT NULL,
  `quantity` int(11) DEFAULT 0,
  PRIMARY KEY (`id`),
  UNIQUE KEY `goods_stock` (`goodsname`,`stockid`)
);

代码说明

  1. 数据接收验证

    • 使用Request::post()获取所有POST数据

    • 检查必须的tabledata字段是否存在

    • 使用json_decode解析JSON数据并捕获异常

  2. 事务处理

    • 使用Db::startTrans()开启事务

    • 所有数据库操作在try块中执行

    • 成功时提交事务Db::commit()

    • 异常时回滚事务Db::rollback()

  3. 主表存储

    • 提取主要订单信息存入order

    • 使用insertGetId获取自增订单ID

  4. 明细数据处理

    • 循环处理每个商品明细

    • 将明细数据关联订单ID存入order_detail

    • 使用where()->dec()原子操作减少库存数量


注意事项

  1. 库存更新逻辑

    • 示例使用dec()方法直接减少库存,确保原子操作

    • 需要根据业务需求确认:

      • number字段是否为出库数量(负数运算)

      • 是否需要检查库存余量(防止负数库存)

  2. 唯一性校验

    • 库存表使用goodsnamestockid组合唯一索引

    • 确保每个商品在每个仓库有唯一记录

  3. 异常处理

    • 捕获所有数据库操作异常

    • 返回友好的错误信息给前端

    • 生产环境建议记录日志Log::error()

  4. 扩展建议

    • 添加数据验证层(Validate)

    • 使用模型替代直接DB操作

    • 添加库存不足的校验逻辑

示例库存校验扩展:

php

复制

// 在更新库存前添加校验
$stock = Db::name('stock')
    ->where('goodsname', $item['goodsname'])
    ->where('stockid', $item['stockid'])
    ->find();

if (!$stock || $stock['quantity'] < $item['number']) {
    throw new \Exception('商品库存不足:' . $item['goodsname']);
}


0

评论区