从旧站 Asteria(Magento 1.x)只读导入商品、用户、评论、订单到本店。源库以 as 为准(不要用 longyishop)。命令共用 Laravel 连接名 asteria,可分批、可断点续跑、可 --dry-run,重复执行不会重复插入。
推荐顺序: 需要清空现有数据时先 reset,再迁商品,再迁用户,再迁订单 / 评论。
php artisan migrate
php artisan catalog:reset --dry-run # 先看会清哪些表
php artisan catalog:reset --force # 清空现有商品,便于重新导入
php artisan products:migrate-asteria # Magento 商品 → flexible_variant,SKU 与旧站一致
php artisan customers:reset --dry-run
php artisan customers:reset --force # 清空现有用户,便于重新导入
php artisan customers:migrate-asteria
php artisan orders:migrate-asteria
php artisan reviews:migrate-asteria --sync # 或走队列,见下文
catalog:reset 会 TRUNCATE 商品及变体 / 库存 / 评论 / 购物车行 / 收藏,并把历史订单行的 product_id 置空(SKU 快照保留)。属性、分类、用户、订单头不删。也可跑 database/scripts/reset_catalog.sql。图片目录加 --purge-files。
customers:reset 会 TRUNCATE 前台用户及地址 / 订阅 / 收藏 / 积分成长值,并把历史订单、评论的 customer_id 置空(邮箱快照保留)。客户分组、后台管理员、商品、订单头不删。也可跑 database/scripts/reset_customers.sql。
.env 中配置只读 Magento 库(应用层只跑 SELECT):
ASTERIA_DB_HOST=127.0.0.1
ASTERIA_DB_PORT=3306
ASTERIA_DB_DATABASE=as
ASTERIA_DB_USERNAME=root
ASTERIA_DB_PASSWORD=
ASTERIA_DB_PREFIX= # Magento 有表前缀时填写,例如 mag_
ASTERIA_DB_CHARSET=utf8
ASTERIA_MEDIA_BASE_URL=https://img.asteriahair.com/media/catalog/product
ASTERIA_STORE_MEDIA_URL=https://img.asteriahair.com/media/
ASTERIA_ATTRIBUTE_FAMILY=wigs
# 留空 = 挂到全部 Bagisto channel;只要部分站点再填 code,逗号分隔
ASTERIA_CHANNELS=
ASTERIA_LOCALES=
连接名默认 asteria,定义在 config/database.php。所有命令都支持 --connection= 覆盖。
跑迁移前确认 Bagisto 侧列已存在:
php artisan migrate
| 表 | 幂等列 | 迁移文件 |
|---|---|---|
products |
migrated_from_asteria_id(unique);SKU 仍唯一 |
database/migrations/2026_09_01_151700_add_asteria_migration_column_to_products_table.php |
customers |
migrated_from_asteria_id(unique),另有 legacy_password、customer_source |
database/migrations/2026_08_20_163200_add_asteria_migration_columns_to_customers_table.php、database/migrations/2026_09_02_144100_add_customer_source_to_customers_table.php |
orders |
migrated_from_asteria_id(unique) |
database/migrations/2026_08_25_143200_add_asteria_migration_column_to_orders_table.php |
product_reviews |
migrated_from_asteria_id(unique) |
评论命令在缺列时会提示,也可交互自动 ALTER TABLE |
商品白名单、变体 Option、图片 URL 前缀在 config/asteria.php(可用 ASTERIA_MEDIA_BASE_URL、ASTERIA_ATTRIBUTE_FAMILY 等覆盖)。
products:migrate-asteria从 Magento 目录只读写入 Bagisto:include_eav_attributes 属性、flexible_variant 商品、图片 URL、库存、按名称匹配的分类、以及由 Custom Option 展开的变体。逻辑对齐 Asteria 的 shell/migrate_to_bagisto.php,落库方式对齐 catalog:sync(不再经 XLS)。
php artisan products:migrate-asteria
php artisan products:migrate-asteria --batch-size=50
php artisan products:migrate-asteria --sku=PC001
php artisan products:migrate-asteria --limit=5 --dry-run
php artisan products:migrate-asteria --attributes-only
php artisan products:migrate-asteria --products-only --no-index
php artisan products:migrate-asteria --reset-progress
源表:catalog_product_entity 及 EAV、catalog_product_entity_media_gallery、cataloginventory_stock_item、catalog_category_product、catalog_product_option*。只导入 Magento status=1(启用)且 SKU 非空的商品。
行为要点:
config/asteria.php 的 include_eav_attributes 创建 Bagisto 属性(select 带选项),并挂到属性族的 general 组。已存在的属性不改类型,只补缺失选项并保证在族里。若跑过 config:cache,改完配置后需要 php artisan config:clear。flexible_variant。属性族优先 wigs,没有则 variant_product / default。product_channels),库存写到这些 channel 关联的全部 inventory_sources。value_per_locale 属性按各 channel 的 locale 各写一份(内容相同);value_per_channel 按各 channel code 各写一份。只要部分站点:ASTERIA_CHANNELS=default,eu 或 config/asteria.php 的 channels。drop_down / radio 作为变体维度(可用 variant_option_titles 白名单,或 skip_option_titles 排除),笛卡尔积写入 product_options / product_variants。图片不下载,写入 Magento 绝对 URL。migrated_from_asteria_id 或相同 SKU:更新(属性 / 图 / 库存 / 变体重建)。--no-index,之后再索引。进度缓存:migrate_asteria_products_last_id(30 天)。--sku= 不写进度。
catalog:sync 仍可从 storage/sync 的 CSV/XLS 导入,适合离线导出;连着 Asteria 库时用本命令。
customers:migrate-asteria同步写入 Bagisto customers + addresses + 订阅(同步、无队列)。
php artisan customers:migrate-asteria
php artisan customers:migrate-asteria --batch-size=200
php artisan customers:migrate-asteria --dry-run
php artisan customers:migrate-asteria --reset-progress
源表:customer_entity、customer_address_entity 及对应 EAV,以及可选的 newsletter_subscriber。
行为要点:
migrated_from_asteria_id 或相同邮箱(不区分大小写):关联,不覆盖姓名/密码,只补未导入的地址。general 分组、默认 Channel;password 为随机 bcrypt,Magento 哈希放在 legacy_password。用户用旧密码登录成功后会自动升级为 bcrypt。phone 置空。addresses.additional.asteria_address_id 去重;街道换行压成 ,。newsletter_subscriber.subscriber_status = 1 为已订阅,写入 customers.subscribed_to_news_letter,并按邮箱幂等写入 subscribers_list。已退订(status=3 等)的注册用户会写成未订阅并保留 subscribers_list 记录;无账号的游客订阅只导入已订阅邮箱。无 newsletter_subscriber 表时跳过,不影响用户导入。重复执行会回填已迁用户的订阅状态。customer_source:从 Magento 客户属性 source 写入。不迁 source_url。已迁用户再跑(--reset-progress)会按 Magento 值回填。进度缓存:migrate_asteria_customers_last_id(30 天)。
reviews:migrate-asteria写入 product_reviews。默认按队列 review-migration 分批投递;--sync 则当场处理。
php artisan queue:work --queue=review-migration # 非 --sync 时需要
php artisan reviews:migrate-asteria
php artisan reviews:migrate-asteria --batch-size=200
php artisan reviews:migrate-asteria --status=1 # 仅 Magento 已审核
php artisan reviews:migrate-asteria --sync
php artisan reviews:migrate-asteria --dry-run
php artisan reviews:migrate-asteria --reset-progress
--status:Magento status_id,1=approved,2=pending,3=not-approved。不传则全部导入,状态映射为 Bagisto 的 approved / pending / disapproved。
关联方式:
catalog_product_entity.sku ↔ Bagisto products.sku。对不上的评论会跳过并打日志。customer_id;没有则游客名(name)。review_media_image 的 URL,后续再批量上 S3(不在本命令内下载文件)。进度缓存:migrate_asteria_reviews_last_id(30 天)。
orders:migrate-asteria同步写入订单头、商品行、账单/收货地址、支付方式。
php artisan orders:migrate-asteria
php artisan orders:migrate-asteria --batch-size=100
php artisan orders:migrate-asteria --dry-run
php artisan orders:migrate-asteria --reset-progress
源表:sales_flat_order、sales_flat_order_item、sales_flat_order_address、sales_flat_order_payment,以及可选的 mw_reward_point_order。
会做:
increment_id 和 created_at,方便用户认历史单号。customers.migrated_from_asteria_id,再按邮箱;都没有则游客单(快照姓名/邮箱仍写入)。product_id 为空。coupon_code 和订单/行折扣金额。不迁 Magento salesrule 规则本身,也不回写券使用次数。mw_rewardpoint、mw_rewardpoint_discount 与 mw_reward_point_order → reward_points_used / reward_points_amount / reward_points_earned。不迁客户积分余额。amcheckoutfees_amount,费用名 insurance / Insurance for Lost)→ shipping_insurance_amount。complete → completed;canceled → canceled;pending_payment / payment_review / pending_paypal → pending_payment;holded → pending;其余常见状态原样对应,未知为 pending。paypal_express / paypal_standard / paypaluk_* → paypal_standard;checkmo → moneytransfer;klarna* → klarna;afterpay* / clearpay* → afterpay。原文写在 order_payment.additional.magento_method。不做: 发票、发货、退款;不扣库存;不触发下单邮件 / 礼品卡等 checkout.order.save.after 事件。
跳过规则:
migrated_from_asteria_id(幂等)。increment_id 已被 Bagisto 现网订单占用(避免覆盖新单)。increment_id 为空。进度缓存:migrate_asteria_orders_last_id(30 天)。
| 选项 | 含义 |
|---|---|
--batch-size |
每批条数;商品默认 100,用户默认 500 |
--dry-run |
只统计,不写库,也不更新进度 |
--reset-progress |
从 ID=0 重新扫(仍幂等,已迁记录会 skip) |
--connection |
源库连接名,默认 asteria |
中断后再次执行会从缓存的 last id 继续。换环境或确认要重扫时加 --reset-progress。
后台管理员、收藏、客户积分余额、购物车 Quote、发票、发货单、退款单、Magento 分类树本身都不在这些命令范围内。商品只按名称挂到已有 Bagisto 分类。订单上的积分抵扣/赚取和丢件险金额会随 orders:migrate-asteria 写入。
连不上 Asteria: 检查 .env 的 ASTERIA_DB_*,以及 Magento 表前缀 ASTERIA_DB_PREFIX。源库必须是 as,不要配成 longyishop。
MySQL 5.6 Unknown column 'generation_expression': Laravel 自带的 Schema::hasColumn() 会查 5.7 才有的 information_schema.columns.generation_expression。迁移脚本已改用 SHOW COLUMNS,可在 5.6 上跑。若 TablePlus 等客户端仍报这个错,是客户端自己在看表结构,与迁移无关。
提示缺列: 先 php artisan migrate。评论列也可在命令交互里自动加。
评论一条都没有 / 大量 skip: 先确认 products:migrate-asteria 后 SKU 与 Magento 一致。
商品属性族找不到: 在 Bagisto 建好 wigs(或改 ASTERIA_ATTRIBUTE_FAMILY / config/asteria.php)。命令会回退到 variant_product、default。
订单是游客单: 先跑用户迁移,并确认 Magento customer_id / 邮箱能对上 migrated_from_asteria_id 或 Bagisto 邮箱。
旧密码登不上: 新迁用户密码在 legacy_password。Web 登录与 API 登录都会走 Magento 1 MD5(可带 salt)校验,成功后改成 bcrypt。已存在的 Bagisto 账号被「关联」时不会写入 legacy_password,仍用原 Bagisto 密码。
重复跑会不会翻倍: 不会。用户按 Asteria ID / 邮箱,地址按 asteria_address_id,商品按 SKU 或 migrated_from_asteria_id(再跑会更新内容),订单/评论按 migrated_from_asteria_id。