我已经尝试搜索这个问题的答案,因为我确信这是以前已经解决过的问题,但我找不到任何讨论cakephp如何格式化从模型返回的数据的内容。通常情况下,我只看到数据是如何来的,并根据每个控制器/视图的需要进行处理。然而,在这种情况下,我想重用我的视图,不幸的是,cakepp将来自不同控制器的数据交给我的方式给我带来了问题。
我有两个模型,关联如下:
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',
)
)
)
在组中使用控制器$this->Group->contain(数组('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',
)
)
无论是主模型还是关联模型,我是否可以更改调用模型数据的方式,使其以一致的方式在不同的控制器上传递?还是我每次都必须循环浏览数据,并以正确的格式重建数据?这似乎意味着,一旦我的数据集增长,它将成为一个效率问题。
获取奇数格式数据的原因是,您使用的包含意味着不获取相关数据(而不是直接数据(。
与其为此实现规范化,我建议修改find((调用:
$group = $this->GroupsController->Group->User->find('list', array(
'conditions' => array('User.group_id' => $id)
));
注意:在不需要的时候使用contain((会为SQL查询添加额外的JOIN,这会影响性能。
我不喜欢规范化/重新格式化我的CakePHP查找数据,因为这会使它成为非标准的。CakePHP总是以可预测的方式返回数据,这只是一个习惯它并使用适当的方法检索数据的问题。
检索直接数据将以以下格式返回:
array(
(int) 0 => array(
'MODEL' => array(
'field1' => 'value1',
'field2' => 'value2',
)
),
(int) 1 => array(
'MODEL' => array(
'field1' => 'value1',
'field2' => 'value2',
)
)
)
检索直接数据和相关数据(通过使用Contain(将以以下格式返回:
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获取相关数据,而不是直接获取。
如果你真的想规范化你的数据(我不建议这样做(,请继续阅读:
有几种方法可以做到这一点,但最合适的方法是在Find((回调之后在模型(或AppModel(中实现数据规范化。
1.3文件:http://book.cakephp.org/1.3/en/The-Manual/Developing-with-CakePHP/Models.html#afterfind
2.x文件:http://book.cakephp.org/2.0/en/models/callback-methods.html#afterfind
在对适用模型的每次查找之后都会调用此回调。在AppModel::afterFind((中实现它将影响应用程序中的每个find调用。
旁注:规范化数据的一个简单方法是使用Set::extract((,然而,根据我的经验,由于实现的健壮性,它可能会比自己循环数据带来更多的开销。看看它是否符合您的需求可能是个好主意。就我个人而言,我自己不会在afterFind((中使用它,因为它可能会添加一些过头的内容,但是,我将它包含在这里,因为它可以满足您的需求。
1.3集合提取文档:
- classicExtract:http://book.cakephp.org/1.3/en/The-Manual/Core-Utility-Libraries/Set.html#classicextract
- 摘录:http://book.cakephp.org/1.3/en/The-Manual/Core-Utility-Libraries/Set.html#extract
2.0设置摘录文档:
- classicExtract:http://book.cakephp.org/2.0/en/core-utility-libraries/set.html#Set::classicExtract
- 摘录:http://book.cakephp.org/2.0/en/core-utility-libraries/set.html#Set::extract
关于效率问题:做一个常规循环根本不会增加太多开销。尽管如此,正常化当然会增加一点开销。
实际上,手动修改数组是不可取的。试图影响模型返回相关数据的方式也是不明智的。
我能想出的最好的办法如下。
假设你的用户索引有类似的东西:
foreach($users as $user) {
debug($user['User']); // made up for brevity
}
在foreach
块的开头添加以下内容:
if (!isset($user['User']) {
$user = array('User' => $user);
}
它似乎没有那么昂贵。