提问者:小点点

如何更改cakephp传递关联模型数据的方式?


我试图寻找这个问题的答案,因为我确信它以前已经解决了,但是我找不到任何讨论cakephp如何格式化从模型返回的数据的东西。通常,我只是看到数据是如何来的,并根据每个Controller/View的需要处理它。然而,在这种情况下,我想重用我的视图,不幸的是,cakephp从不同的控制器向我传递数据的方式给我带来了问题。

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

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

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

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

我发现我可以用$this-

在UsersController::index()中,我将调用$users=$this-

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

在GroupsController中使用$this-

它返回一个组列表,但采用此格式,而不是debug($group['User'])

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

    )
)

我是否可以改变调用模型数据的方式,使其以一致的方式在不同的控制器上传递,无论是主模型还是关联模型?或者我每次都必须循环浏览数据并以正确的格式重新构建数据?这似乎是一旦我的数据集增长,它将成为一个效率问题。


共2个答案

匿名用户

之所以以奇数格式获取数据,是因为您使用的是contain,这意味着无法获取相关数据(而不是直接数据)。

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

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

注意:在不需要时使用contain()会向SQL查询添加额外的连接,这将影响性能。

我不喜欢规范化/重新格式化我的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获取相关数据,而不是直接获取。

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

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

>

  • 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::afterfint()中实现它会影响应用中的每个查找调用。

    旁注:规范化数据的一个简单方法是使用Set::extract(),然而,根据我的经验,由于实现的健壮性,它可能会比自己循环数据造成更多的开销。看看是否适合你的需要可能是个好主意。就我个人而言,我不会在afterFind()中使用它,因为它可能会添加一些过头的内容,但是,我将它包括在这里,因为它可能适合您的需要。

    1.3设置提取留档:

    • 分类摘录:http://book.cakephp.org/1.3/en/The-Manual/Core-Utility-Libraries/Set.html#classicextract

    2.0设置提取留档:

    • 分类摘录:http://book.cakephp.org/2.0/en/core-utility-libraries/set.html#Set::classicExtract

    关于效率问题:执行常规循环不会增加太多开销。尽管如此,正常化当然会增加一点开销。

  • 匿名用户

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

    我能想出的最好的办法如下。

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

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

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

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

    这似乎没那么贵。