【问题标题】:Provide a human-readable representation of an identifier?提供标识符的人类可读表示?
【发布时间】:2011-06-22 18:03:49
【问题描述】:

作为previous question 的后续行动,我要求解决一个已损坏的问题,我试图找到一种以“可读”方式表达任意标识符的方法。

上下文:我们正在使用具有身份实体(来自DDD的域模型对象)。此身份(映射到数据库主键)可以表示为字符串:'123''ABC'

一些实体可以有一个复合身份,即由两个或多个其他实体的身份组成:array('123','ABC')

有时,我们想要漂亮地打印这个身份,或者在只允许单个字符串的地方使用它(例如,在 HTML <option> 值中)。该过程必须是可预测和可逆的,即如何将其反转回其原始状态不应有歧义。

当我们想要人工读取这个身份时,出于调试目的,阅读123ABC123~ABC 而不是a:2:{i:0;s:3:"123";i:1;s:3:"ABC";} 更容易,这就是我们不这样做的原因不想使用serialize()json_encode()等内置函数。

json_encode() 做得很好,但是在 HTML 中使用它时,引号必须正确编码,它变得非常不可读:

<option value="[&quot;123&quot;,&quot;ABC&quot;]">

我们可以在哪里使用像这样的好格式:

<option value="123~ABC">

当发布 HTML 表单时,我们必须能够将此编码的 identity 恢复到其原始状态:array('123','ABC') 以检索正确的 entity

最后,如果 identity 包含除字母和数字之外的其他字符,则格式变得复杂(人工)阅读是完全可以接受的。

一些基本的例子:

'123' => '123'
'ABC' => 'ABC'
array('123','ABC') => '123~ABC'(只是一个想法)

'string with non-alphanumeric, even non-àscìì char$' => ?

包含其他字符的字符串可以接受任何(或多或少复杂的)表示。结果字符串应该只包含 ASCII 字符,即使原始字符串包含非 ASCII 字符。整个过程必须是完全可逆的。

你知道怎么做吗?

【问题讨论】:

  • 实体的有效字符是什么?
  • 任何字符都对身份有效,因为它在数据库字符串主键中。但在现实生活中,大部分时间都是由可读字符组成的。这就是编码应该同时兼顾两者的原因。
  • 那么你说的是哪个字符集?它可以用 Unicode 代码点表达吗?
  • 好点。字符集应该无关紧要。如果原始字符串包含非 ASCII 字符,那么对它们进行编码以使其也适合 ASCII 字符集将是一个很好的解决方案。我更新了我的问题以反映这一点。

标签: php orm domain-driven-design identity identifier


【解决方案1】:

根据您在 cmets 中提供的反馈,我建议您使用 urlencoderawurlencode 编码标识符原子

然后您可以使用, 冒号创建原子组合。

class Identifier {
    static function encode(array $identifier) {
        return implode(', ', array_map('rawurlencode', $identifier));
    }
    static function decode($identifier) {
        return array_map('rawurldecode', 
            array_map('trim', explode(',', $identifier))
        );
    }
}

$identifier = array('111', 'abc');
var_dump($identifier);

$encoded = Identifier::encode($identifier);
var_dump($encoded);

$decoded = Identifier::decode($encoded);
var_dump($decoded);

【讨论】:

  • 这是一个非常有趣和简单的方法,它确实解决了上面所说的问题,谢谢!
  • 感谢这个编写良好的代码,它很少能突出显示它。我只是删除逗号后的空格(IMO 没用),这似乎完美地解决了我的问题:return implode(',', array_map('rawurlencode', $identifier));return array_map('rawurldecode', explode(',', $identifier));
  • 请考虑其他人可能会在文件中编辑这些标识符并可能在周围添加空格。因此修剪。输出严格,但接受输入不严格。
  • 我看不到用户必须编辑标识符的用例,但为什么不呢,我理解你的意思。对于人类可读的要求,这两种方法都是有效的,尽管我可能更喜欢最简单的一种(人类可写现在不是一个问题)。非常感谢您的帮助,这是一项出色的工作!
  • 类用作命名空间?这是一个禁忌:)
【解决方案2】:
str_replace( array('[',']','&quot;',',') ,
             array('','','','~'),
            json_encode($stuff)
);

您的问题非常冗长,无法解释您真正想要达到的目标。

【讨论】:

  • 大声笑,与 other question 中的 cmets 完全相反,这解释了冗长。我认为它确实很好地解释了我想要实现的目标,我只是在问题中添加了另一句话,也许不是那么明显:“发布 HTML 表单时,何时必须能够将其恢复为原始状态检索正确的实体”。关于您的代码,您不解释如何反转它?
  • @Benjamin:编辑您的问题(删除所有内容并)发布一系列示例以及您希望如何转换它。我也会相应地编辑我的答案
  • 感谢您的建议,我将添加一些示例,但不会删除问题,上一个问题的人确实想了解问题的上下文。
【解决方案3】:

您可以使用 2 个特殊字符:

~ - 分隔符

* - 转义字符(转义分隔符或转义字符本身)

例子:

array('123','ABC') => 123~ABC
array('12*3','A~BC') => 12**3~A*~BC

您可以为分隔符和转义符选择不同的字符。如果选定的字符很少使用,那么字符串通常可读性很好。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-16
    • 1970-01-01
    • 2010-09-05
    • 2023-01-17
    • 2011-08-28
    相关资源
    最近更新 更多