1

首先,我想说我知道如何为我的问题创建丑陋的解决方案。我正在寻找好的解决方案和最佳实践:)

如何从 Kohana 3 ORM 对象(包括关系类型为一对多的相关对象)创建深层层次数组(稍后为 json_encode)?

问题是 ORM->as_array() 方法确实对“有一个”和“属于”关系递归地工作,但是当你遇到一个“有很多”关系时会停止并强制你手动使用 ->find_all() .

假设我正在使用 Kohana 3 和内置 ORM 创建一个 JSON API REST 服务器。当有人查看此 URL 时:www.example.com/api/user?id=5 他们将为 id=5 的用户提供 JSON 对象。

这些是 orm 模型和关系:

  • 用户 属于一个国家
  • 用户 有很多 消息
  • 消息 属于一个类别

我希望这个工作:

echo json_encode(
ORM::factory('user', 5)
->with('country')
->with('messages')
->with('messages:category')
->find()
->as_array()
);

并给我这样的输出:

{
    name: "John"
    age: 54,
    country_id: 5,
    country: {
        name: 'Sweden',
        code: 'SE'
    },
    messages: {
        {
            content: 'Lorem ipsum dolor...',
            category_id: 1,
            category: {...}
        },
        {
            content: 'Sit amet elit...',
            category_id: 2,
            category: {...}
        },
        {
            content: 'Consectetur ipsum dolor...',
            category_id: 3,
            category: {...}
        }
    }
}

但这行不通。这就是你会得到的一切:

{
    name: "John"
    age: 54,
    country_id: 5,
    country: {
        name: 'Sweden',
        code: 'SE'
    }
}

有人分叉或扩展了 Kohana 3 ORM 以支持这种功能吗?
有人知道以某种方式为您解决这个问题的任何好的 Kohana 3 api 模块吗?

4

1 回答 1

0

据我所知,仅使用 ORM 是无法做到这一点的。出现这种情况有两个原因:

  1. 如果 amessage与 有关系category,那通常意味着与类别中的category有对应关系。messages如果您想获得message“完整”——即包括其类别——假设您还想获得category“完整”——即包括其消息。这显然是一个非常糟糕的主意,因为您可以很容易地将自己设计成一个无限循环。换句话说,如果有一个神奇的“递归所有关系”能力,它怎么知道什么时候停止递归?

  2. 当您调用时,ORM 在幕后所做的一切find()就是构建一个 SQL 查询,该查询从数据库中返回一行数据。但是,对于返回单行的单个查询,您尝试做的事情太复杂了。(有一种方法可以使用MySQL 的GROUP_CONCATfunction将多行检索为一行,每个字段中的值用逗号分隔,但我向你保证,这不值得麻烦。)

由于这两个原因,ORM 的with()方法仅适用于belongs_to(在您的情况下,是user'scountrymessage's category)。

执行此查询的一种方法是将其分为三个步骤,如下所示:

// Step 1: Get the user
$user = ORM::factory('user', 5)
    ->with('country')
    ->find();

// Step 2: Get the messages
$user->messages
    ->with('category')
    ->find_all();

// Step 3: Make user and the messages into arrays.
// User is easy, but messages are a little harder
// because they need to turn
//     from "an object containing an array of objects"
//     into "an array of arrays."
$user_arr = $user->as_array();
$fixer = function($obj)
{
    return $obj->as_array();
};
$user_arr['messages'] = array_map($fixer, $user->messages->as_array());

// Now you can output it
echo json_encode($user_arr);
于 2013-12-30T03:55:11.337 回答