You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel跨数据库复制Eloquent模型记录报错排查

问题描述

我需要将mysqlProducts数据库中ind_products表内指定product_id的记录复制到mysqlOrders数据库的cart_ind_products表中,同时设置指定的cart_product_id。

我的模型定义如下:

class IndProduct extends Model {
  use HasFactory;

  protected $connection = 'mysqlProducts';

  protected $table = "ind_products";

  protected $fillable = [
    'product_id',
    'name',
    'category',
    'subcategory',
    'description',
    'price_VAT_excl_per_unit',
    'price_VAT_incl_per_unit',
    'weight',
    'breed',
    'kind',
    'age',
    'bio',
    'grass_fed',
    'drying_time',
    'nr_of_pieces',
    'lifestyle',
    'part_of_animal',
    'confirmed',
    'saved',
  ];

  // 单个商品属于一个商品(关联关系)
  public function products() {
    return $this->setConnection('mysqlProducts')->belongsTo(Product::class, 'product_id', 'id');
  }
}

class CartIndProduct extends Model {
  use HasFactory;

  protected $connection = 'mysqlOrders';

  protected $table = "cart_ind_products";

  protected $fillable = [
    'cart_product_id',
    'product1_id',
    'name',
    'category',
    'subcategory',
    'description',
    'price_VAT_excl_per_unit',
    'price_VAT_incl_per_unit',
    'weight',
    'breed',
    'kind',
    'age',
    'bio',
    'grass_fed',
    'drying_time',
    'nr_of_pieces',
    'lifestyle',
    'part_of_animal',
    'confirmed',
    'saved',
  ];

  // 购物车单个商品属于一个购物车商品(关联关系)
  public function cart_products() {
    return $this->setConnection('mysqlOrders')->hasOne(CartProduct::class, 'cart_product_id', 'id');
  }
}

第一次尝试的代码及错误

控制器代码

public function createCartIndProducts(Request $request, $cart_product_id, $product_id) {
  $ind_products = IndProduct::on('mysqlProducts')->where('product_id', '=', $product_id)->get()->toArray();

  foreach($ind_products as $ind_product) {
    CartIndProduct::on('mysqlOrders')->insert($ind_product);
  }
  return response()->json([
    "status" => 1,
    "message" => "Cart individual products registered successfully in database.",
  ], 200);
}

错误信息

SQLSTATE[22007]: 无效的日期时间格式:1292 列 'created_at' 的日期时间值 '2022-10-28T19:54:12.000000Z' 不正确(SQL:insert into cart_ind_products (id, name, category, subcategory, description, price_VAT_excl_per_unit, price_VAT_incl_per_unit, weight, created_at, updated_at, product_id, breed, kind, age, bio, grass_fed, drying_time, nr_of_pieces, lifestyle, part_of_animal, confirmed, saved) values (656, ?, Aardappelen, ?, ?, 0.00, 0.00, ?, 2022-10-28T19:54:12.000000Z, 2022-10-28T19:54:12.000000Z, 903, bjbg, ?, ?, 0, ?, ?, ?, ?, ?, 1, 1))

第二次尝试的代码及错误

控制器代码

public function createCartIndProducts(Request $request, $cart_product_id, $product_id) {
  $ind_products = IndProduct::on('mysqlProducts')->where('product_id', '=', $product_id)->get();

  foreach($ind_products as $ind_product) {
    $cart_ind_product = IndProduct::on('mysqlProducts')->$ind_product->replicate()->fill(
        ['cart_product_id' => $cart_product_id, ]
      );
    $cart_ind_product->CartIndProduct::on('mysqlOrders')->save();
  }
  return response()->json([
    "status" => 1,
    "message" => "Cart individual products registered successfully in database.",
    //    "data" => $cart_ind_products,
  ], 200);
}

错误信息

属性 [{"id":656,"name":null,"category":"Aardappelen","subcategory":null,"description":null,"price_VAT_excl_per_unit":"0.00","price_VAT_incl_per_unit":"0.00","weight":null,"created_at":"2022-10-28T19:54:12.000000Z","updated_at":"2022-10-28T19:54:12.000000Z","product_id":903,"breed":"bjbg","kind":null,"age":null,"bio":0,"grass_fed":null,"drying_time":null,"nr_of_pieces":null,"lifestyle":null,"part_of_animal":null,"confirmed":1,"saved":1}] 不存在于Eloquent构造器实例上。

请问我哪里操作有误?


问题分析与解决

第一次尝试的错误原因

  • 日期格式不兼容:get()->toArray()会把Eloquent模型的created_at/updated_at转换成带时区的ISO格式字符串,但MySQL的datetime字段不支持这种格式,导致插入失败。
  • 字段不匹配:原表的product_id在目标表中对应product1_id,直接插入会导致字段映射错误,同时目标表必填的cart_product_id未设置。
  • 主键冲突风险:直接复制原表的id字段,可能和目标表已有主键冲突。

第二次尝试的错误原因

代码语法错误:IndProduct::on('mysqlProducts')->$ind_product写法完全错误,$ind_product已经是查询返回的IndProduct实例,不需要再通过模型构造器调用,这行代码相当于试图访问Eloquent构造器上以整个模型JSON为名称的属性,必然报错。

正确的实现代码

public function createCartIndProducts(Request $request, $cart_product_id, $product_id) {
    // 从源数据库获取目标记录
    $indProducts = IndProduct::on('mysqlProducts')
        ->where('product_id', $product_id)
        ->get();

    foreach ($indProducts as $indProduct) {
        // 复制模型实例,排除主键、时间戳字段
        $cartIndProduct = $indProduct->replicate(['id', 'created_at', 'updated_at']);
        
        // 映射字段并设置cart_product_id
        $cartIndProduct->fill([
            'cart_product_id' => $cart_product_id,
            'product1_id' => $indProduct->product_id // 源表product_id对应目标表product1_id
        ]);
        
        // 切换到目标数据库并保存
        $cartIndProduct->setConnection('mysqlOrders')->save();
    }

    return response()->json([
        "status" => 1,
        "message" => "购物车单个商品已成功注册到数据库。",
    ], 200);
}

关键改进点

  1. 使用replicate()复制模型:自动处理模型属性,避免手动数组转换带来的格式问题,同时可指定排除不需要复制的字段(如主键、时间戳)。
  2. 明确字段映射:将源表product_id对应到目标表product1_id,同时设置必填的cart_product_id。
  3. 切换数据库连接:通过setConnection()为复制后的模型指定目标数据库,确保保存到正确的表中。
  4. 自动生成时间戳:Laravel会自动为新保存的模型生成符合MySQL格式的created_at和updated_at值,无需手动处理。

内容的提问来源于stack exchange,提问作者Isabelle

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 18:31:44