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

PHP中使用多态替代条件语句实现多类型产品统一入库

PHP基于OOP多态实现通用产品入库方案

实现核心:通过抽象基类约定公共产品逻辑,各类型产品独立成类实现自身属性校验、持久化逻辑,配合工厂类自动匹配产品实例,全程无产品类型相关的条件判断,仅需单端点即可支持所有产品的入库操作。

数据库结构设计

按范式拆分公共表和各类型专属属性表:

  • 公共产品表 products:存储所有产品共有字段
    字段说明:
    • product_id:主键,自增
    • name:varchar类型,产品名称
    • price:decimal类型,产品价格
    • product_type:varchar类型,存储产品类型标识(laptop/tv/speakers)
    • created_at:timestamp类型,创建时间,默认当前时间
  • 各类型专属属性表:
    • laptop_attributes:存储笔记本专属属性,字段含product_id(外键关联products表主键)、cpu、ram、ssd
    • tv_attributes:存储电视专属属性,字段含product_id(外键关联)、size
    • speaker_attributes:存储音箱专属属性,字段含product_id(外键关联)、power、channels

类文件实现

所有产品类独立存放,核心依赖抽象类约束统一行为,靠多态分发逻辑。

1. 抽象产品基类 AbstractProduct.php

封装所有产品的公共属性校验、公共入库逻辑,强制子类实现自身专属逻辑:

<?php
abstract class AbstractProduct {
    protected PDO $db;
    protected string $name;
    protected float $price;
    protected string $productType;

    public function __construct(PDO $db, string $name, float $price, string $productType) {
        $this->db = $db;
        $this->name = $name;
        $this->price = $price;
        $this->productType = $productType;
        $this->validateCommonAttributes();
    }

    // 公共属性校验逻辑
    protected function validateCommonAttributes(): void {
        if (trim($this->name) === '') {
            throw new InvalidArgumentException("产品名称不能为空");
        }
        if ($this->price <= 0) {
            throw new InvalidArgumentException("产品价格必须大于0");
        }
    }

    // 公共入库流程:先写公共表,再调子类方法写专属属性
    public function save(): int {
        $stmt = $this->db->prepare("INSERT INTO products (name, price, product_type) VALUES (?, ?, ?)");
        $stmt->execute([$this->name, $this->price, $this->productType]);
        $productId = (int)$this->db->lastInsertId();
        $this->saveSpecificAttributes($productId);
        return $productId;
    }

    // 强制子类实现的抽象方法:专属属性校验、专属属性入库
    abstract protected function validateSpecificAttributes(): void;
    abstract protected function saveSpecificAttributes(int $productId): void;
}

2. 笔记本类 Laptop.php

独立类文件,实现笔记本专属的参数处理、校验、入库逻辑:

<?php
class Laptop extends AbstractProduct {
    protected string $cpu;
    protected string $ram;
    protected string $ssd;

    public function __construct(PDO $db, array $params) {
        parent::__construct($db, $params['name'], (float)$params['price'], 'laptop');
        $this->cpu = trim($params['cpu'] ?? '');
        $this->ram = trim($params['ram'] ?? '');
        $this->ssd = trim($params['ssd'] ?? '');
        $this->validateSpecificAttributes();
    }

    protected function validateSpecificAttributes(): void {
        if ($this->cpu === '' || $this->ram === '' || $this->ssd === '') {
            throw new InvalidArgumentException("笔记本需完整填写CPU、内存、硬盘参数");
        }
    }

    protected function saveSpecificAttributes(int $productId): void {
        $stmt = $this->db->prepare("INSERT INTO laptop_attributes (product_id, cpu, ram, ssd) VALUES (?, ?, ?, ?)");
        $stmt->execute([$productId, $this->cpu, $this->ram, $this->ssd]);
    }
}

3. 电视类 TV.php

独立类文件,实现电视专属逻辑:

<?php
class TV extends AbstractProduct {
    protected string $size;

    public function __construct(PDO $db, array $params) {
        parent::__construct($db, $params['name'], (float)$params['price'], 'tv');
        $this->size = trim($params['size'] ?? '');
        $this->validateSpecificAttributes();
    }

    protected function validateSpecificAttributes(): void {
        if ($this->size === '') {
            throw new InvalidArgumentException("电视需填写尺寸参数");
        }
    }

    protected function saveSpecificAttributes(int $productId): void {
        $stmt = $this->db->prepare("INSERT INTO tv_attributes (product_id, size) VALUES (?, ?)");
        $stmt->execute([$productId, $this->size]);
    }
}

4. 音箱类 Speakers.php

独立类文件,实现音箱专属逻辑:

<?php
class Speakers extends AbstractProduct {
    protected string $power;
    protected string $channels;

    public function __construct(PDO $db, array $params) {
        parent::__construct($db, $params['name'], (float)$params['price'], 'speakers');
        $this->power = trim($params['power'] ?? '');
        $this->channels = trim($params['channels'] ?? '');
        $this->validateSpecificAttributes();
    }

    protected function validateSpecificAttributes(): void {
        if ($this->power === '' || $this->channels === '') {
            throw new InvalidArgumentException("音箱需完整填写功率、声道参数");
        }
    }

    protected function saveSpecificAttributes(int $productId): void {
        $stmt = $this->db->prepare("INSERT INTO speaker_attributes (product_id, power, channels) VALUES (?, ?, ?)");
        $stmt->execute([$productId, $this->power, $this->channels]);
    }
}

5. 产品工厂类 ProductFactory.php

负责根据请求参数自动实例化对应产品类,是唯一维护类型和类映射关系的位置:

<?php
class ProductFactory {
    // 类型映射表,后续新增产品类型仅需在此追加配置即可
    protected static array $typeMap = [
        'laptop' => Laptop::class,
        'tv' => TV::class,
        'speakers' => Speakers::class
    ];

    public static function create(PDO $db, array $params): AbstractProduct {
        $type = strtolower(trim($params['product_type'] ?? ''));
        if (!isset(self::$typeMap[$type])) {
            throw new InvalidArgumentException("不支持的产品类型");
        }
        return new self::$typeMap[$type]($db, $params);
    }
}

通用保存端点实现

仅需一个接口文件save_product.php,所有类型产品的新增请求都走这个端点,无任何类型判断逻辑:

<?php
header('Content-Type: application/json');
try {
    // 初始化数据库连接
    $db = new PDO(
        'mysql:host=localhost;dbname=替换为你的库名;charset=utf8mb4',
        '替换为你的数据库账号',
        '替换为你的数据库密码'
    );
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    // 引入类文件,实际项目可使用composer自动加载替代手动引入
    require_once 'AbstractProduct.php';
    require_once 'Laptop.php';
    require_once 'TV.php';
    require_once 'Speakers.php';
    require_once 'ProductFactory.php';

    // 生成对应产品实例,调用save完成入库
    $product = ProductFactory::create($db, $_POST);
    $productId = $product->save();

    echo json_encode([
        'code' => 0,
        'msg' => '保存成功',
        'product_id' => $productId
    ], JSON_UNESCAPED_UNICODE);
} catch (Exception $e) {
    http_response_code(400);
    echo json_encode([
        'code' => 1,
        'msg' => $e->getMessage()
    ], JSON_UNESCAPED_UNICODE);
}

实现说明

  • 全程没有使用if/else、switch等条件语句判断产品类型,不同产品的属性差异完全通过多态特性自动分发处理
  • 每类产品对应独立类文件,耦合度低,后续新增产品类型只需要新增对应类文件、在工厂映射表追加配置,不需要修改原有逻辑和端点代码
  • 所有产品新增请求统一走save_product.php端点,不需要为不同产品类型单独开发接口
  • 公共逻辑和专属逻辑拆分清晰,公共属性校验、入库逻辑在基类统一维护,避免重复代码

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 20:01:19