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

在Symfony API架构中定义固定数据的最优方案

在Symfony API中处理固定静态数据的方案(骰子游戏场景)

针对你的骰子游戏需求,下面给出几种适合Symfony架构的实现方案,根据数据复杂度和业务逻辑选择即可:

方案一:PHP枚举(Enum)—— 静态数据首选

如果只是存储骰子的标签、数值范围这类纯静态数据,PHP 8.1+的枚举是最简洁高效的方案,自带类型安全,维护成本极低。

实现代码

// src/Enum/DiceType.php
namespace App\Enum;

enum DiceType: string
{
    case STANDARD_6 = 'standard_6';
    case ODD_10 = 'odd_10';
    case EVEN_10 = 'even_10';

    // 获取骰子显示标签
    public function getLabel(): string
    {
        return match($this) {
            self::STANDARD_6 => '1-6标准骰子',
            self::ODD_10 => '1-10奇数骰子',
            self::EVEN_10 => '1-10偶数骰子',
        };
    }

    // 获取骰子数值范围
    public function getValueRange(): array
    {
        return match($this) {
            self::STANDARD_6 => range(1, 6),
            self::ODD_10 => range(1, 10, 2),
            self::EVEN_10 => range(2, 10, 2),
        };
    }

    // 输出所有骰子数据(用于API接口返回)
    public static function getAll(): array
    {
        return array_map(fn(self $type) => [
            'key' => $type->value,
            'label' => $type->getLabel(),
            'range' => $type->getValueRange(),
        ], self::cases());
    }
}

在API控制器中使用

// src/Controller/DiceController.php
namespace App\Controller;

use App\Enum\DiceType;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Routing\Annotation\Route;

#[Route('/api/dice-types')]
class DiceController extends AbstractController
{
    #[Route('', methods: ['GET'])]
    public function list(): JsonResponse
    {
        return $this->json(DiceType::getAll());
    }
}

方案二:服务标签 + Tagged Iterator —— 复杂逻辑场景

如果每个骰子需要独立的业务逻辑(比如不同的掷骰算法、校验规则),Symfony的服务标签+Tagged Iterator是符合依赖注入最佳实践的方案,扩展性极强。

步骤1:定义骰子接口

// src/Interface/DiceInterface.php
namespace App\Interface;

interface DiceInterface
{
    public function getKey(): string;
    public function getLabel(): string;
    public function getValueRange(): array;
    public function roll(): int; // 示例:掷骰方法
}

步骤2:实现具体骰子服务

// src/Dice/Standard6Dice.php
namespace App\Dice;

use App\Interface\DiceInterface;

class Standard6Dice implements DiceInterface
{
    public function getKey(): string { return 'standard_6'; }
    public function getLabel(): string { return '1-6标准骰子'; }
    public function getValueRange(): array { return range(1, 6); }
    public function roll(): int { return rand(1, 6); }
}
// src/Dice/Odd10Dice.php
namespace App\Dice;

use App\Interface\DiceInterface;

class Odd10Dice implements DiceInterface
{
    public function getKey(): string { return 'odd_10'; }
    public function getLabel(): string { return '1-10奇数骰子'; }
    public function getValueRange(): array { return range(1, 10, 2); }
    public function roll(): int {
        $range = $this->getValueRange();
        return $range[array_rand($range)];
    }
}

步骤3:给服务打标签

在config/services.yaml中为骰子服务添加统一标签:

services:
    App\Dice\Standard6Dice:
        tags: ['app.dice']

    App\Dice\Odd10Dice:
        tags: ['app.dice']

    App\Dice\Even10Dice:
        tags: ['app.dice']

步骤4:创建骰子注册表

用TaggedIterator自动注入所有带标签的骰子服务:

// src/Registry/DiceRegistry.php
namespace App\Registry;

use App\Interface\DiceInterface;
use Symfony\Component\DependencyInjection\Attribute\TaggedIterator;

class DiceRegistry
{
    /** @var iterable<DiceInterface> */
    private iterable $dices;

    public function __construct(
        #[TaggedIterator('app.dice')] iterable $dices
    ) {
        $this->dices = $dices;
    }

    /** @return DiceInterface[] */
    public function getAll(): array
    {
        return iterator_to_array($this->dices);
    }

    public function getByKey(string $key): ?DiceInterface
    {
        foreach ($this->dices as $dice) {
            if ($dice->getKey() === $key) {
                return $dice;
            }
        }
        return null;
    }
}

步骤5:在控制器中使用注册表

// src/Controller/DiceController.php
namespace App\Controller;

use App\Registry\DiceRegistry;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Routing\Annotation\Route;

#[Route('/api/dice-types')]
class DiceController extends AbstractController
{
    public function __construct(private DiceRegistry $diceRegistry) {}

    #[Route('', methods: ['GET'])]
    public function list(): JsonResponse
    {
        $data = array_map(fn($dice) => [
            'key' => $dice->getKey(),
            'label' => $dice->getLabel(),
            'range' => $dice->getValueRange(),
        ], $this->diceRegistry->getAll());

        return $this->json($data);
    }

    #[Route('/{key}/roll', methods: ['POST'])]
    public function roll(string $key): JsonResponse
    {
        $dice = $this->diceRegistry->getByKey($key);
        if (!$dice) {
            return $this->json(['error' => '骰子类型不存在'], 404);
        }

        return $this->json(['result' => $dice->roll()]);
    }
}

方案三:工厂类 —— 动态实例创建场景

如果需要根据参数动态创建骰子实例,工厂类是简单直接的选择,但扩展性不如标签迭代器(新增骰子需修改工厂代码)。

实现代码

// src/Factory/DiceFactory.php
namespace App\Factory;

use App\Dice\Even10Dice;
use App\Dice\Odd10Dice;
use App\Dice\Standard6Dice;
use App\Interface\DiceInterface;

class DiceFactory
{
    public function create(string $key): ?DiceInterface
    {
        return match($key) {
            'standard_6' => new Standard6Dice(),
            'odd_10' => new Odd10Dice(),
            'even_10' => new Even10Dice(),
            default => null,
        };
    }

    public function getAllKeys(): array
    {
        return ['standard_6', 'odd_10', 'even_10'];
    }
}

方案选择建议

  • 纯静态数据(仅标签、范围):优先用PHP枚举,最简洁高效。
  • 每个骰子有独立业务逻辑:用服务标签+Tagged Iterator,符合Symfony最佳实践,扩展性强。
  • 需要动态创建实例:用工厂类,适合简单场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 20:50:37