0

我已经尝试寻找这个问题的答案,因为我确定它之前已经整理过,但我找不到任何讨论 cakephp 如何格式化从模型返回的数据的内容。通常我只是看到数据是如何来的,并根据每个控制器/视图的需要处理它。然而,在这种情况下,我想重用我的视图,不幸的是 cakephp 将来自不同控制器的数据交给我的方式给我带来了问题。

我有 2 个模型,关联如下:

class Group extends AppModel {
public $hasMany = array(  'User' ); 
}

class User extends AppModel {
public $belongsTo = array(
'Group'  ); 
}

我想向View/Groups/view/id 我展示各个组的详细信息,以及属于该组的用户列表。理想情况下,我不想重新创建代码来显示用户列表,因为它已经存在于View/Users/index

我发现我可以使用 $this->extend('/Users/index') 但我不能像我想要的那样只使用 `$this->set('users',$group['User']),因为数组的构建方式不同。

在 UsersController::index() 我会调用$users = $this->find('all');它给出这样的用户列表:debug($users);

array(
(int) 0 => array(
    'User' => array(
        'id' => '100',
        'group_id' => '101', 
    )
),
(int) 1 => array(
    'User' => array(
        'id' => '101',
        'group_id' => '101',
    )
)
)

在 GroupsController 中使用 $this->Group->contain(array('User')); $group = $this->GroupsController->Group->find('first','conditions'=>array('id'=>$id);

它返回组列表,但采用这种格式debug($group['User']);

 'User' => array(
    (int) 0 => array(
        'id' => '101',
        'group_id' => '101', 
    ),
    (int) 1 => array(
        'id' => '100',
        'group_id' => '101',

    )
)

无论如何我可以改变我调用模型数据的方式,让它在不同的控制器上以一致的方式传递,无论是主模型还是关联模型?还是我每次只需要循环浏览数据并以正确的格式重建数据?这似乎一旦我的数据集增长,它将成为一个效率问题。

4

2 回答 2

0

您以奇数格式获取数据的原因是因为您使用的是包含这意味着不会获取相关数据(不是直接数据)。

我建议不要为此实施规范化,而是修改您的 find() 调用:

$group = $this->GroupsController->Group->User->find('list', array(
    'conditions' => array('User.group_id' => $id)
));

注意:在不需要时使用 contains() 会在 SQL 查询中添加额外的 JOIN,这会影响性能。

我不想规范化/重新格式化我的 CakePHP 查找数据,因为它使它不标准。CakePHP 总是以可预测的方式返回数据,这只是习惯它并使用适当的方法来检索数据的问题。

检索直接数据将以以下格式返回:

  array(
    (int) 0 => array(
        'MODEL' => array(
            'field1' => 'value1',
            'field2' => 'value2', 
        )
    ),
    (int) 1 => array(
        'MODEL' => array(
            'field1' => 'value1',
            'field2' => 'value2',
        )
    )
  )

检索直接数据和相关数据(通过使用包含)将以以下格式返回:

  array(
    (int) 0 => array(
        'MODEL' => array(
            'field1' => 'value1',
            'field2' => 'value2', 
            'RELATEDMODEL' => array(
                (int) 0 => array(
                    'field1' => 'value1'
                    'field2' => 'value2'
                ),
                (int) 1 => array(
                    'field1' => 'value1'
                    'field2' => 'value2'
                )
            )
        )
    ),
    (int) 1 => array(
        'MODEL' => array(
            'field1' => 'value1',
            'field2' => 'value2',
            'RELATEDMODEL' => array(
                (int) 0 => array(
                    'field1' => 'value1'
                    'field2' => 'value2'
                ),
                (int) 1 => array(
                    'field1' => 'value1'
                    'field2' => 'value2'
                )
            )
        )
    )
  )

您的数据不同的原因是因为您告诉 MySQL 获取相关数据而不是直接获取它。

如果您真的想规范化您的数据(我不建议这样做),请继续阅读:

有几种方法可以做到这一点,但最合适的方法是在模型(或 AppModel)的 afterFind() 回调中实现数据规范化。

每次找到适用模型后都会触发此回调。在 AppModel::afterFind() 中实现它会影响应用中的每个查找调用。

旁注:标准化数据的一种简单方法是使用 Set::extract(),但是,根据我的经验,由于实现的健壮性,它可能比您自己循环数据导致更多开销。看看它是否符合您的需求可能是个好主意。就个人而言,我自己不会在 afterFind() 中使用它,因为它可能会增加开销,但是,我将它包括在这里,因为它可能符合您的需求。

1.3 设置提取文档:

2.0 设置提取文档:

关于效率问题:执行常规循环根本不会增加太多开销。然而,话虽如此,规范化当然会增加一点开销。

于 2013-04-23T00:20:42.310 回答
0

事实上,手动修改数组是不可取的。试图影响模型返回关联数据的方式也是不明智的。

我能想到的最好的方法如下。

假设您的用户索引具有以下内容:

foreach($users as $user) {
    debug($user['User']); // made up for brevity
}

在块的开头添加以下内容foreach

if (!isset($user['User']) {
    $user = array('User' => $user);
}

这似乎并没有那么昂贵。

于 2013-04-23T00:13:24.347 回答