gpt4 book ai didi

Is there a way to reference objects in a registry as if it was an enum?(有没有一种方法可以引用注册表中的对象,就好像它是一个枚举?)

转载 作者:bug小助手 更新时间:2023-10-26 21:09:54 25 4
gpt4 key购买 nike



I'm working on a web game project which has the concept of items.

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


Individual instances of items, which a user could have in their inventory, are stored in the database. Each of those rows has a column called item_base which is used in the code to get details about the item. Example:

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























unique_item_id player_id item_base
3345346 43455 ITEM_ONE
3856739 97212 ITEM_TWO


My ItemBase class:

我的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();
}

}

The ItemType enum is just a standard enum that returns a string to prevent typos.

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


I'm looking to "register" all of my item bases in the codebase rather than its own table in the database since I want to prevent additional queries. Each item base also has a function ($action) to determine which code should be executed when the item is used, and I'm avoiding putting PHP directly into the database.

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


Creating a new item base would be like this:

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


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 ItemBase::ITEM_ONE. Then I can use ItemBase::ITEM_ONE->name or the other variables passed through the construct.

我的目标是能够引用ItemBase::Item_One之类的项库。然后,我可以使用ItemBase::Item_One->名称或通过构造传递的其他变量。


What is the best way to approach this? Being able to have the defined type (which IDEs also support type completion on) is preferred over using an $array['string'] lookup. Since enums can't be backed by an object, can I do something with a registry type class?

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


I've tried creating a class with all of my ItemBases in them and then registering each one similar to this:

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


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

This then allows me to use ItemBase::ITEM_ONE(), but I'm looking for a method that doesn't require a function for each item base in the game.

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


更多回答
优秀答案推荐

You can use a regsitry class and the __callStatic magic method

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


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", "Item One", "Food", function () {
return "foo";
});
echo ItemStore::ITEM_ONE()->name;
echo "\n";
echo ItemStore::ITEM_ONE()->action;


ITEM_ONE is not a valid item


Item One


foo



You could optionally define the registry stuff on the ItemBase class instead of making a separate ItemStore class.

您可以选择在ItemBase类上定义注册表内容,而不是创建单独的ItemStore类。



Why not use the name of the enum entry as key in a lookup array? It is a distinct value, so perfectly usable as key in a map.

为什么不使用枚举条目的名称作为查找数组中的键?它是一个独特的值,因此可以完美地用作map中的key。


enum ItemType {
case FOOD;
case DRINK;
}

readonly class ItemBase {

public function __construct(
public string $name,
// public ItemType $itemType, // not needed, as the key in $registry is the link
public Closure $action
) {}

}

$registry = [
ItemType::FOOD->name => new ItemBase('Item One', fn() => 'food'),
ItemType::DRINK->name => new ItemBase('Item One', fn() => 'drink'),
];

echo $registry[ItemType::FOOD->name]->name;
echo "\n";
echo ($registry[ItemType::FOOD->name]->action)();

Output:

产出:


Item One
food

Note the parentheses around the lookup and property access for action. The parentheses are necessary because the function call () has higher precedence than the property access with ->.

请注意操作的查找和属性访问周围的圆括号。圆括号是必需的,因为函数调用()比使用->访问属性具有更高的优先级。


Or the same with a (type safe) registry class:

或与(类型安全)注册表类相同:


enum ItemType {
case FOOD;
case DRINK;
}

readonly class ItemBase {

public function __construct(
public string $name,
public ItemType $itemType,
public Closure $action
) {}

}

readonly class Registry implements ArrayAccess {

private array $items;

public function __construct(
ItemBase ...$itemBases
) {
$items = [];
foreach ($itemBases as $item) {
$items[$item->itemType->name] = $item;
}
$this->items = $items;
}

final public function offsetExists(mixed $offset): bool {
return is_string($offset) && array_key_exists($offset, $this->items);
}

final public function offsetGet(mixed $offset): mixed {
return $this->offsetExists($offset) ? $this->items[$offset] : null;
}

final public function offsetSet(mixed $offset, mixed $value): void {
throw new RuntimeException();
}

final public function offsetUnset(mixed $offset): void {
throw new RuntimeException();
}

}

$registry = new Registry(
new ItemBase('Item One', ItemType::FOOD, fn() => 'food'),
new ItemBase('Item One', ItemType::DRINK, fn() => 'drink'),
);

echo $registry[ItemType::FOOD->name]->name;
echo "\n";
echo ( $registry[ItemType::FOOD->name]->action )();

更多回答

Thank you! This fits my needs although I need to see if I can get PHPStorm to autocomplete the potential options when using the __callStatic magic method. I'm able to call these bases dynamically by getting the string value from the database then using ItemBase::{$item->base_item}().

谢谢!这符合我的需要,尽管我需要查看在使用__allStatic魔术方法时,是否可以让PHPStorm自动完成可能的选项。我可以通过从数据库获取字符串值,然后使用ItemBase::{$Item->base_Item}()来动态调用这些库。

Phpstorm will autocomplete if you provide @method phpdoc for each method, meaning you'd still need to specify a doc comment for each method, which is annoying, but I don't think there's any sort of dynamic autocomplete you can do. If you figure that out lmk!

如果您为每个方法提供了@方法phpdoc,那么PhpStorm将自动完成,这意味着您仍然需要为每个方法指定一个文档注释,这很烦人,但我不认为有任何类型的动态自动完成是可以做的。如果你想明白这一点,好吗!

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com