我有一个images表和一个servers表。 images具有一个server_id字段,该字段是id表中servers字段的外键。 servers表中还有一个名为name的字段,这是我要检索的字段。

这是我的控制器操作代码:

$images = $this->Image->find('all', array(
    'conditions' => array('Image.user_id' => $this->Auth->user('id')),
    'order' => array('Image.uploaded DESC')
));
$this->set('images', $images);


它获取如下数据:

Array
(
    [0] => Array
        (
            [Image] => Array
                (
                    [id] => 103
                    [orig_name] => Untitled-5.jpg
                    [hash] => MnfWKk
                    [filename] => MnfWKk.jpg
                    [uploaded] => 2012-07-12 00:09:08
                    [views] => 0
                    [album_id] =>
                    [user_id] => 15
                    [server_id] => 1
                )

        )
)


我想从server_id表中获取name字段,而不是servers。如何调整我的find()方法来获取此信息?我知道这是一个SQL连接,但我不知道如何告诉Cake进行操作以获取服务器名称。

谢谢。

最佳答案

TLDR:

设置正确的CakePHP associations,然后使用CakePHP's Containable。 (使用recursive -1)。

较长的说明:

最佳做法是将查找代码保留在模型本身中,这就是我将要演示的内容,但是可以随意(如果需要)将其移回控制器。

通过这种方式,您可以从任何控制器调用相同的getImages()函数,并且仅根据要返回的内容传递不同的参数。这样进行编码的好处是,您始终知道是否要查找与查询/数据库相关的代码,就应该在模型中查找。当下一个查看您的代码的人不必去搜索时,这是非常有益的。

由于在图像和服务器之间建立了关联,因此您可以在查询图像时“包含”服务器信息。但是-在指定要使模型为$actAs = array('Containable');之前,您不能使用“包含”。 [ CakePHP Book: Containable ]

最后,在您的AppModel中,设置$recursive = -1;是一个好习惯。这使得所有型号的默认值为-1。如果出于某种原因您不赞成这样做,则只要确保在使用containable时将递归设置为-1。而且-一旦您学会了使用容器,就再也不会回头了-它很棒。还有更多可以做的事情

码:

//AppModel *******
//...
$recursive = -1;
//...

//Images controller *******
//...
public function whatever() {
    $opts = array();
    $opts['user'] = $this->Auth->user('id');
    $images = $this->Image->getImages($opts);
    $this->set(compact('images'));
}
//...


//Image model *******
//...
public $actsAs = array('Containable');

public belongsTo = array('Server');

public function getImages($opts = array()) {

    $params = array('condtions'=>array());

    //specific user
    if(!empty($opts['user'])) {
        array_push($params['conditions'], array('Image.user_id'=>$opts['user']);
    }

    //order
    $params['order'] = 'Image.uploaded DESC';
    if(!empty($opts['order'])) {
        $params['opts'] = $opts['order'];
    }

    //contain
    $params['contain'] = array('Server');

    //returns the data to the controller
    return $this->find('all', $params);
}


其他一些注意事项


您还应该在服务器模型中设置关联。
我给出的代码示例相当冗长(这是一个单词吗?)。随心所欲地凝结
您还可以扩展模型的getImages()方法,以接受更多参数,例如find,limit ... etc。自定义您想要的所有内容-这不是实现它的方式-与我通常使用的类似。
根据您的问题,如果只需要一个字段,则可以在“包含”中指定所需的字段-有关详细信息,请参见本书。
现在看来似乎令人困惑,但是值得正确学习如何正确地做这些事情-它会让您的生活更轻松。

08-28 04:42