在基于REST的Web应用程序中保留继承的概念

时间:2013-03-20 14:00:42

标签: javascript rest inheritance

我们正在构建一个新的单页面前端来替换我们的web-app的旧静态html前端(带有一些jquery)。在这样做时,我们遇到了一个关于我们从api返回的对象类型的问题。

当我们从PHP后端导出数据作为JSON时,我们包含一个额外的字段,我们在导出之前放置对象所具有的类型。我们可以使用它来处理我们请求的资源的不同子类。

然而,有时我们也想区分父类。请考虑以下情形:

继承树:

Animal
    Mammal
        Human
        Dog
        ...
    Reptile
        Crocodile
        Snake
        ...

GET / animals /

[
    {"_type": "Human", "id": 1, "food": "Ice Cream"},
    {"_type": "Human", "id": 2, "food": "Steak"},
    {"_type": "Human", "id": 3, "food": "Peanut Butter"},
    {"_type": "Dog", "id": 4, "food": "Horse Poop"}
    {"_type": "Crocodile", "id": 5, "food": "Humans"}
]

当我有一个UI,我希望展示所有的动物,但例如突出所有的哺乳动物,我有一个问题,因为我已经失去了哺乳动物的知识。

我们提出的最简单的解决方案是在从后端导出对象时包含继承链。可能是这样的:

{
    "_type": "Human",
    "id": 10,
    "food": "Ice Cream",
    "_parentClasses": "Animal.Mammal.Human"
}

虽然我认为这不是一个特别好的解决方案,但它很容易实现和使用,而且看起来很健壮。

你认为这是一个好/好/坏主意,你是如何解决这个问题的?

5 个答案:

答案 0 :(得分:1)

在我看来,引起你心痛的事情是你的对象在输出上变平。也许GET / Animals应该返回更多类似的东西:

[
    {"Mammals": {   
        {"_type": "Human", "id": 1, "food": "Ice Cream"},
        {"_type": "Human", "id": 2, "food": "Steak"},
        {"_type": "Human", "id": 3, "food": "Peanut Butter"},
        {"_type": "Dog", "id": 4, "food": "Horse Poop"}
    },
    {"Reptiles": {
        {"_type": "Crocodile", "id": 5, "food": "Humans"}
    }
]

如果您可以在输出中保留对象的结构,当您将该复杂对象发送回服务器时,您的结构应保持不变。

答案 1 :(得分:1)

有很多选择。这是我没见过的一个:

使_type数组而不是字符串,第一项包含当前类和其余父类。

{
    "_type": ["Human","Mammal","Animal"],
    "id": 10,
    "food": "Ice Cream"
}

这应该很容易在PHP方面实现:

$_type = array_keys(class_parents($this));
array_unshift($_type, get_class($this));

答案 2 :(得分:1)

许多好的答案,这是您可能想要考虑的另一种选择。

您只能使用JSON将子类发送到客户端,然后客户端会对其基类进行查找。它将一些复杂性从服务器端移动到客户端,并使您的JSON消息保持清洁。

答案 3 :(得分:0)

我可以看到几种可能实现这一目标的方法。您可以开发REST服务器以接受URI,例如:

/animals/mammal/humans 
/animals/mammal/dog
/animals/reptile/crocodile

或者,只需返回上面所述的对象类型即可。从类型构建对象。

<?php
    $object = null;     

    switch($_type){
      case 'human':
          $object = new Human();
      break;

      case 'dog':
          $object = new Dog();
      break;

      case 'crocodile':
        $object = new Crocodile();
      break;
    }
?>

关于我如何解决这个问题只是我的两分钱。

答案 4 :(得分:0)

不确定这是否有资格作为答案,真的(或者甚至该问题属于问题!!),但几年前我在时间管理器上使用了类似的过程;以类似的方式完成继承路径。我发现使用它非常简单,更直观,而且一些替代方案基本上会导致更多的工作。

为了扩展简单性,我还打破了OOP的正常规则,不仅允许父母知道孩子,还让孩子知道父母。它确实为代码添加了一点但它可行,并且再次使整个过程不那么痛苦。