我正在从事一个网络游戏项目,其中有项目的概念.

用户可以在其库存中拥有的物品的各个实例存储在数据库中.这些行中的每一行都有一个名为item_base的列,该列在代码中用于获取有关项目的详细信息.示例:

unique_item_id player_id item_base
3345346 43455 ITEM_ONE
3856739 97212 ITEM_TWO

我的ItemBase个班级:

class ItemBase {

    public $name;
    public $type;
    public $action;

    public function __construct(string $name, ItemType $type, callable $action) {
        $this->name = $name;
        $this->type = $type->value;
        $this->action = $action();
    }

}

ItemType枚举只是一个标准的枚举,它返回一个字符串以防止输入错误.

我希望在代码库中"注册"我的所有项目库,而不是在数据库中注册它自己的表,因为我想防止额外的查询.每个项库还有一个函数($action),用于确定在使用项时应该执行哪些代码,并且我避免将PHP直接放入数据库中.

创建新的项目库将如下所示:

new ItemBase("Item One", ItemType::FOOD, function() {
    //Code to execute when the function is called
});

My goal is to be able to reference item bases with something like 100.,然后我可以使用ItemBase::ITEM_ONE->name或通过构造传递的其他变量.

解决这一问题的最佳方式是什么?能够定义类型(IDE也支持类型完成)比使用$ARRAY[‘STRING’]查找更可取.由于枚举不能由对象支持,我能对注册表类型类做些什么吗?

我try 创建一个包含所有ItemBase的类,然后注册每个类,如下所示:

public static function ITEM_ONE() {
    return new ItemBase("Item One", ItemType::FOOD, function() {
        //Code to execute when the function is called
});

这允许我使用ItemBase::ITEM_ONE(),但我正在寻找一种方法,它不需要为游戏中的每个物品库提供函数.

推荐答案

您可以使用regsitry类和__callStatic魔术方法

class ItemStore {
    protected static $store = [];

    public static function registerItem($key, $name, $type, $action) {
        self::$store[$key] = compact("name", "type", "action");
    }

    public static function __callStatic($key, $args) {
        if (array_key_exists($key, self::$store)) {
            return new ItemBase(
                self::$store[$key]["name"],
                self::$store[$key]["type"],
                self::$store[$key]["action"]
            );
        }
        throw new \InvalidArgumentException("$key is not a valid item");
    }
}

// demo

try {
    echo ItemStore::ITEM_ONE()->name;
} catch (\InvalidArgumentException $e) {
    echo $e->getMessage();
}
echo "\n";

ItemStore::registerItem("ITEM_ONE", "第一项", "Food", function () {
    return "富";
});
echo ItemStore::ITEM_ONE()->name;
echo "\n";
echo ItemStore::ITEM_ONE()->action;

Item_One不是有效的项目

第一项

您可以 Select 在ItemBase类上定义注册表内容,而不是创建一个单独的ItemStore类.

Php相关问答推荐

条纹 checkout :订阅试用版和额外付款(add_invoice_items)错误

如何使用查询范围在Statamic中按组过滤用户?

根据在WooCommerce购物车和 checkout 中 Select 的送货方式显示快捷代码内容

有没有办法为整个PHP应用程序启用严格类型

可以';exec、system和shell_exec PHP函数中的命令字符串上的字符数不得超过8175

$this->;db->;update();CodIgnitor中的功能不工作

使用简码在 WooCommerce 我的帐户中显示一些用户数据

按类别层次 struct 过滤 Laravel 集合

有没有办法像引用枚举一样引用注册表中的对象?

PHP 支持 APNG 文件吗?

invalid_grant 和无效的 JWT 签名

将 PHP 版本更改为 8.1,但 WordPress 认为我们正在使用版本 7.4?

如何更新 Laravel Eloquent 列强制转换为集合

向元素添加类时添加循环错误

ACF 更新字段功能不更新 WordPress 中的任何数据

在wordpress注销后防止后退操作

服务器遇到内部错误或配置错误,无法完成您的请求

从 CSV 文件 seeder 数据库时的额外行

Symfony 6 中的入口点 (public/index.php) - 它是如何工作的?

Docker: unixodbc.h 没有这样的文件或目录.已安装 unixodbc-dev 时出现pecl install sqlsrv错误