我有一个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。自定义您想要的所有内容-这不是实现它的方式-与我通常使用的类似。
根据您的问题,如果只需要一个字段,则可以在“包含”中指定所需的字段-有关详细信息,请参见本书。
现在看来似乎令人困惑,但是值得正确学习如何正确地做这些事情-它会让您的生活更轻松。