php 防伪溯源项目:防伪码生成与批量写入实践

目录

一、项目背景与防伪码要求

二、核心实现思路

三、数据库表设计(唯一性兜底)

四、16位数字防伪码生成方法

[1. 使用 ThinkPHP Helper 助手函数(推荐)](#1. 使用 ThinkPHP Helper 助手函数(推荐))

[2. 使用 FastAdmin 自带随机函数(推荐)](#2. 使用 FastAdmin 自带随机函数(推荐))

[3. 自定义随机数生成函数](#3. 自定义随机数生成函数)

五、防伪码批量生成与写入方案

[1. 简单递归生成(适合小批量)](#1. 简单递归生成(适合小批量))

[2. 批量生成唯一防伪码(MySQL查重)](#2. 批量生成唯一防伪码(MySQL查重))

[六、基于 Redis 的唯一防伪码生成](#六、基于 Redis 的唯一防伪码生成)

[七、批量写入 insertAll() 使用规范](#七、批量写入 insertAll() 使用规范)

总结


一、项目背景与防伪码要求

在防伪溯源项目中, 第一步就是创建防伪码。防伪码的设计需满足以下要求:

  • 全局唯一性
  • 16位纯数字字符串,随机生成
  • 支持高效批量写入

二、核心实现思路

  • 16位纯数字防伪码 由于PHP的int类型无法承载16位数字,直接生成字符串格式的16位数字,避免溢出丢失精度。
  • 唯一性保障 采用"预生成 + 查重 + 批量插入"方案,结合MySQL唯一索引做最终兜底,双重防止重复。
  • 高效批量插入 整理符合模型要求的二维数组,使用ThinkPHP模型的insertAll()高效插入,兼顾性能和框架规范。

三、数据库表设计(唯一性兜底)

确保防伪码字段为字符串类型,并添加唯一索引,防止重复:

php 复制代码
CREATE TABLE `fa_secure_code` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `batch_no` varchar(32) DEFAULT '' COMMENT '批次',
  `secure_code` varchar(32) DEFAULT '' COMMENT '防伪码',
  `goods_id` int(11) DEFAULT NULL COMMENT '商品ID',
  `status` tinyint(1) DEFAULT '1' COMMENT '状态 1正常 0 禁用',
  `create_date` datetime DEFAULT NULL COMMENT '创建时间',
  `update_date` datetime DEFAULT NULL COMMENT '更新时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `ux_secure_code` (`secure_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='防伪码';

四、16位数字防伪码生成方法

1. 使用 ThinkPHP Helper 助手函数(推荐)

php 复制代码
// 安装依赖
composer require topthink/think-helper
// 生成随机字符串
$code =  Str::random(16, 1);

2. 使用 FastAdmin 自带随机函数(推荐)

php 复制代码
$code = Random::numeric(16);

3. 自定义随机数生成函数

php 复制代码
function random_number(int $length = 16)
{
    $str = '';
    for ($i = 0; $i < $length; $i++) {
        $str .= random_int(0, 9);
    }
    return $str;
}

五、防伪码批量生成与写入方案

1. 简单递归生成(适合小批量)

php 复制代码
public static function createSecureCode(): string
{
    $str = Str::random(16, 1);
    $find = SecureCode::where('secure_code', $str)->find();
    if ($find) {
        return self::createSecureCode();
    }
    return $str;
}

public static function batchAdd($count, $goodsId)
{
    $batch = date('YmdHis');
    for ($i = 0; $i < $count; ++$i) {
        transaction(function () use ($batch, $goodsId) {
            $data = [
                'batch_no' => $batch,
                'goods_id' => $goodsId,
                'status' => 1,
                'secure_code' => SecureCode::createSecureCode(),
            ];
            $secure = SecureCode::create($data);
        });
    }
}

2. 批量生成唯一防伪码(MySQL查重)

核心逻辑:

  • 批量生成16位数字字符串
  • 查重去重
  • 整理数据格式
  • insertAll()批量插入,处理唯一索引冲突
php 复制代码
public static function batchAddV2($count, $goodsId)
{
    // 初步生成
    $code_list = SecureCode::getCodeList($count);
    // 过滤重复的code
    $ux_code_list = SecureCode::filterCodes($code_list);

    while (\count($ux_code_list) < $count) {
        $need_count = $count - \count($ux_code_list);
        $_code_list = SecureCode::getCodeList($need_count);
        $_ux_code_list = SecureCode::filterCodes($_code_list);
        $ux_code_list = array_merge($ux_code_list, $_ux_code_list);
        $ux_code_list = array_unique($ux_code_list);
    }

    $ux_code_list = \array_slice($ux_code_list, 0, $count);
}

public static function getCodeList(int $count, array $list = [])
{
    $origin_count = \count($list);
    $target_count = $count - $origin_count;
    for ($i = 0; $i < $target_count; ++$i) {
        $list[] = Str::random(16, 1);
    }
    $list = array_unique($list);

    if (\count($list) < $count) {
        return self::getCodeList($count, $list);
    }

    return \array_slice($list, 0, $count);
}

/**
 * 过滤重复的code
 */
public static function filterCodes($code_list)
{
    $codes = self::whereIn('bar_code', $code_list)->column('bar_code');
    return array_filter($code_list, function ($code) use ($codes) {
        return !\in_array($code, $codes);
    });
}

六、基于 Redis 的唯一防伪码生成

核心优势:

  • Redis Set 天然去重:SADD命令自动忽略重复,无需手动查重。
  • 内存级高效操作:所有操作均在内存中,效率远高于MySQL的WHERE IN查询。
  • 原子性保障:单线程模型,避免高并发下的重复。
  • 双重兜底安全:Redis Set去重 + MySQL唯一索引兜底。
    实现示例:
php 复制代码
public static function batchAddV3($count, $goodsId)
{
    $key = 'secure_code_list_set';

    // 1. 数据一致性同步(兜底,避免Redis数据丢失)
    $current_count = redis_utils()->sCard($key);
    if (!$current_count) {
        SecureCode::field('id,secure_code')
            ->chunk(1000, function ($list) use ($key) {
                $dbCodes = array_column($list, 'secure_code');
                redis_utils()->sAdd($key, ...$dbCodes);
            });
    }

    $code_list = SecureCode::getCodeList($count);
    $ux_code_list = SecureCode::redisFilterCodes($key, $code_list);

    while (\count($ux_code_list) < $count) {
        $need_count = $count - \count($ux_code_list);
        $_code_list = SecureCode::getCodeList($need_count);
        $_ux_code_list = SecureCode::redisFilterCodes($key, $_code_list);
        $ux_code_list = array_merge($ux_code_list, $_ux_code_list);
        $ux_code_list = array_unique($ux_code_list);
    }
}

public static function redisFilterCodes($key, $code_list)
{
    foreach ($code_list as $index => $code) {
        if (redis_utils()->sIsMember($key, $code)) {
            unset($code_list[$index]);
        }
    }
    return array_unique($code_list);
}

七、批量写入 insertAll() 使用规范

使用ThinkPHP模型的insertAll()进行批量插入:

php 复制代码
$data = [];
$batch = date('YmdHis');
for ($i = 0; $i < $count; ++$i) {
    $data[] = [
        'batch_no' => $batch,
        'goods_id' => $goodsId,
        'status' => 1,
        'secure_code' => $ux_code_list[$i],
        'create_date' => date('Y-m-d H:i:s'),
        'update_date' => date('Y-m-d H:i:s'),
    ];
}

SecureCode::insertAll($data);

总结

  • 防伪码生成需保证唯一性高效性,推荐使用字符串存储和唯一索引兜底。
  • 批量生成时可结合MySQL查重或Redis Set天然去重,提升性能。
  • 最终插入建议使用insertAll(),大幅提升批量操作效率。
    如需进一步探讨,欢迎交流!
相关推荐
设计师小聂!14 小时前
宝塔 Linux 面板保姆级教程
linux·mysql·开源·运维开发
Tong Z15 小时前
Mysql DDL中的ALGORITHM
数据库·mysql
minji...19 小时前
MySQL数据库 (七) MySQL表的基本查询(上),insert、replace、select、where、order by
数据库·mysql·select·replace·insert·order by·where
绵绵细雨中的乡音20 小时前
监控显示一切正常,可用户根本打不开网站——Blackbox Exporter帮我找到了真相(1)
开发语言·php
折戟不必沉沙21 小时前
mysql忘记密码
数据库·mysql
kuonyuma21 小时前
MyBatis入门·注解操作
java·spring boot·mysql·spring·mybatis
聪明努力的积极向上21 小时前
【claude code】MySQL MCP 配置完整指南
数据库·mysql·ai编程
DIY源码阁21 小时前
JavaSwing酒店管理系统 - MySQL版
java·mysql·eclipse
川石课堂软件测试21 小时前
UI自动化测试|元素操作&浏览器操作实践
功能测试·测试工具·mysql·ui·docker·容器·单元测试
右耳朵猫AI1 天前
PHP周刊2026W22 | WordPress 7.0发布、Laravel 13.10.0、Polyfill 1.38.1、Symfony 8.1
php·laravel·symfony