robthree / humanoid
友好的ID生成器。将整数转换为文字,反之亦然
Requires
- php: ^7.4 || ^8.0
- ext-json: *
- spatie/enum: ^3.12
Requires (Dev)
- infection/infection: ^0.26
- php-parallel-lint/php-parallel-lint: ^1.3
- phpbench/phpbench: ^1.2
- phpstan/phpstan: ^1.5
- phpunit/phpunit: ^9.5.20
- spatie/phpunit-snapshot-assertions: ^4.2
- squizlabs/php_codesniffer: *
- vimeo/psalm: ^4.22
This package is auto-updated.
Last update: 2024-09-19 05:43:41 UTC
README
此类可以用于生成“友好ID”,其中数值ID被替换为文字。一个著名的例子是Gfycat,它使用"形容词形容词动物
": https://gfycat.com/gracefulspanishgemsbuck
。
此类有两个方法:create(int $id)
,它返回从ID生成的字符串,以及parse(string $text)
,它返回从解析的文本中获取的ID。它支持自定义单词/类别列表,可选分隔符和可选格式。
快速入门
安装
composer require robthree/humanoid
用法
use RobThree\HumanoID\HumanoIDs; // Create new instance of HumanoID via the builder $zooIdGen = HumanoIDs::zooIdGenerator(); // Convert ID to HumanoID $zooId = $zooIdGen->create(96712); echo sprintf("HumanoID : %s\n", $zooId); // Convert back to ID $id = $zooIdGen->parse($zooId); echo sprintf("Decoded ID : %d\n", $id);
输出(取决于使用的单词列表)
HumanoId : 'sick-yellow-wolf'
Decoded ID : 96712
我们提供了一些内置的zooIdGenerator
和spaceIdGenerator
,但很容易(且推荐)通过实现HumanoIDInterface
来创建自己的HumanoID
。
API
HumanoID
有一个包含4个参数的构造函数;除了第一个参数外,其余都是可选的
$wordSets
:用作‘字典’的单词结构(见下文)$categories
(可选,见下文):如果您想使用与默认顺序不同的类别顺序(默认顺序是$words
参数的键的顺序)$separator
(可选,见下文):要使用(如果有的话)的分隔符$format
(可选,见下文):要使用的格式
HumanoID
有两个公开方法
create(int $id): string
:将整数转换为IDparse(string $text): int
:将文本转换为整数
单词列表和类别
您可以使用自定义单词列表;您可以将这些存储在您想要的地方,例如JSON文件或数据库中。只要您使用以下数据结构初始化HumanoID
类
[
'adjectives' => ['big', 'smart', 'funky'],
'colors' => ['red', 'green', 'blue'],
'animals' => ['cow', 'whale', 'monkey'],
]
《HumanoID》将自动确定哪些“类别”可用。在上面的示例中,生成的HumanoID将采用形容词-颜色-动物
的形式。如果这还不够,HumanoID会自动重复第一个类别,直到满足需求;因此,这将导致形容词-形容词-颜色-动物
或甚至形容词-形容词-形容词-颜色-动物
等等。但是,可以通过将单词数组传递给HumanoID
类的$categories
参数来指定类别顺序。例如,您可以传递['colors', 'adjectives', 'animals']
,这将导致HumanoID采用颜色-形容词-动物
的形式,或者再次,如果这还不够:颜色-颜色-颜色-形容词-动物
。
当然,您不必使用形容词、颜色和动物。可以是任何您想要的东西。所以,更一般化地说,您可以提供任何形式的数据结构
[
'category1' => ['value', 'value', 'value', ...],
'category2' => ['value', 'value', 'value', ...],
...
]
分隔符
默认情况下,HumanoID
使用-
字符来分隔单词,这会导致HumanoID的形式为大-红-鲸鱼
。您可以指定任何所需的字符串作为分隔符;如果分隔符字符串不包含在任何单词中,则这有助于。
可以指定一个空(''
)或null
分隔符。这将导致类似于bigredwhale
的HumanoID。这与Gfycat网址看起来最接近。然而,您需要极其小心,确保单词不会重叠。例如,如果形容词同时包含old
和cold
,则HumanoIDgenericoldpanda
将导致歧义的结果("generi", "cold", "panda" 与 "generic", "old", "panda")。通过精心生成的单词表,这不应该成为问题。
格式
支持一些格式,可以在构建HumanoID
类的实例时指定。当前支持的格式通过WordFormatOption
枚举类提供。
提供的选项包括
WordFormatOption::ucfirst
,WordFormatOption::lcfirst
,WordFormatOption::upper
,WordFormatOption::lower
,以及- 无格式(
null
)。
所有选项都像它们的名称所暗示的那样工作;因此,ucfirst
将导致Big-Red-Whale
,而upper
将导致BIG-RED-WHALE
。"无格式"选项只是保留单词从提供的单词集中格式化。
工作原理
ID(整数)到HumanoID转换
create(int $id): string
方法接受ID并基本上执行类似于将十进制值967
转换为十六进制值3C7
的基数转换。
然而,这一次我们并没有16个"数字"(0..9,A..F),而是任意数量的代表一个数字的单词。
HumanoID到ID(整数)转换
parse(string $text): int
方法基本上是create
方法的相反操作;它接受一个字符串并尝试执行另一种基数转换,类似于将十六进制值3C7
转换为十进制值967
。然而,这一次要复杂得多...
如果我们可以假设字符串中始终有一个"每个数字"的分隔符,我们就可以简单地在分隔符处拆分字符串并进行计算。即使没有使用分隔符,例如,使用ucfirst
选项(导致BigRedWhale
),我们也可以很容易地拆分单词。
然而;我们希望尽可能接近Gfycat实现。这使事情变得复杂。这基本上意味着我们有以下要求:URL应该是大小写不敏感的,并且包含一个可选分隔符。
HumanoID的解码依赖于在初始化HumanoID
类时创建的查找表(顺便说一下,这是一个相当昂贵的操作;如果您需要生成或解析多个HumanoID,请尽可能保留实例!)。
我们不会过多地深入细节,但基本上是在每个字符的基础上创建一个树,顺序相反。在解码HumanoID时,算法从字符串的末尾开始工作,同时沿着这棵树向下移动,并在相应的类别中查找单词索引。一旦确定索引,就可以在基-N转换中使用它,算法继续进行,直到到达HumanoID的开始或查找失败。
一般建议
- 不要在生产中更改您的单词列表。想象一下重新分配或重新排序十六进制系统中的值
A..F
。这将非常困难,如果不正确,将导致HumanoID到ID的转换错误,或者导致歧义结果等。 - 使用大型单词列表。不要过度使用,但只有几个单词的分类帮助不大(除非您不介意HumanoID过长(例如
red-blue-blue-red-red-blue-funky-monkey
)或者有更多较小的分类)。 - 无论您决定使用什么样的单词列表/分隔符/格式,一旦您选择了它,您就别无选择(除非您想要破坏所有的HumanoID或者您需要做一些(即时)转换)。
- 在不使用任何分隔符的情况下,尽量使用较长的、唯一的单词,这些单词不包含在其他单词中(例如,避免使用"
old
,cold
"或"expensive
,inexpensive
")。 - 如果无法避免或希望使用没有分隔符的模糊词语,您可以仅考虑使用
create(int $id)
方法,并将结果与id
一起存储在您的数据中。如果可能,请应用唯一约束和索引。这样,您就可以使用具有 HumanoID 值的字段进行查找。 - 如前所述;尽可能长时间地保留此类。构造函数包含一些相当耗CPU的代码(构建查找表),因此理想情况下,您应该尽可能长时间地保持实例存活。
注意
“模糊词语”问题 可能 在稍后版本中通过将迭代查找过程更改为递归算法来解决;这样,当查找失败(例如,cold
、old
等)时,可以递归地尝试下一个值,直到 HumanoID 完全正确解码(或仍然完全失败)。
基准测试
一些基本、初步的基准测试可以在 这里 找到,还有更多正在制作中。
发音
HumanoID 发音为 "humano i d"(《ˈhjuːmənəʊ aɪ diː》),但如果您喜欢取悦机器人,"humanoid"(《ˈhjuːmənɔɪd》)也可以。
许可
在 MIT 许可证下授权。有关详细信息,请参阅 LICENSE。
标志和图标基于 Vectorslab(#7323564)和 Those Icons(#523788)在 FlatIcon 上的图标。