2012-07-11 44 views
0

我有一個images表和servers表。 images有一個server_id字段,它是servers表中id字段的外鍵。 servers表也有一個名爲name的字段,這是我想要檢索。SQL與JOIN的CakePHP

這裏是我的控制器動作代碼:

$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,我想從servers表得到name領域。我怎樣才能使我的find()方法得到這個?我知道這是一個SQL連接,但我不知道如何告訴Cake做一個以獲得服務器名稱。

謝謝。

回答

1

TLDR:

設置正確的CakePHP associations,並使用CakePHP's Containable。 (與recursive -1)。

較長的描述:

這是保持你發現的代碼模型本身最佳實踐,所以這就是我會告訴,但隨時(如果必須)將其移動回控制器。

這樣做可以讓您從任何控制器調用相同的getImages()函數,並根據您想返回的內容傳遞不同的參數。像這樣編碼的好處是,你總是知道如果你正在尋找與查詢/數據庫相關的代碼,你應該看看模型。當看到你的代碼的下一個人不必去搜索時,這是非常有益的。

由於在圖像和服務器之間建立了關聯,因此您可以在查詢圖像時「包含」服務器信息。但是 - 除非您指定要將模型設置爲$actAs = array('Containable');,否則不能使用「包含」。 [ CakePHP Book: Containable ]

最後,在您的AppModel中,最好設置$recursive = -1;。這使所有型號的默認值爲-1。如果由於某種原因,您反對這樣做,只要確保在您使用可容納的任何時候將遞歸設置爲-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等等。自定義這一切你想要的 - 這不是做它的方式 - 就像我通常使用的。
  • 根據你的問題,如果你只需要一個字段,你可以在「包含」中指定你想要的字段 - 查看書中的細節。
  • 現在看起來可能很混亂,但它是值得學習如何做到這一點正確的 - 它會讓你的生活更輕鬆。
+0

很好這是一個巨大的* *的幫助。謝謝。總得說這樣的事情讓我真的很喜歡Cake,我來自CodeIgniter,而Cake看起來好多了。 :) – 2012-07-12 01:12:30

+0

Np,很高興提供幫助。我同意 - CakePHP太棒了! – Dave 2012-07-12 12:17:43

0

蛋糕有很多模型關係實現this。看看這個頁面,我想你會被使用屬於關聯關係

0

簡單而另一種方法爲begginers

$images = $this->Image->find('all', array(
    'conditions' => array('Image.user_id' => $this->Auth->user('id')), 
    'joins' => array(
        array(
         'table' => 'servers', 
         'alias' => 'Server', 
         'type' => 'inner', //join of your choice left, right, or inner 
         'foreignKey' => true, 
         'conditions' => array('Image.server_id=Server.id') 
        ), 
       ), 
    'order' => array('Image.uploaded DESC') 
)); 

這在性能