2015-01-07 26 views
1

我有這個模型場景(遵循僞代碼):子女關係對象發現在我的CakePHP 2.0項目

model Product { 
    int id; 
    Video video; 
} 

model Video { 
.... 
} 

我想使用CakePHP $這個 - >產品 - >找到( '全部')來獲取我所有的產品和相關視頻。 CakePHP的給我一個多維數組的結果是這樣的:

{ 
    Product: { 
     id: "3", 
     video_id: "1", 
    }, 
    Video: { 
     id: "1", 
     url: "c", 
}, 
{ 
    Product: { 
     id: "3", 
     video_id: "1", 
    }, 
    Video: { 
     id: "1", 
     url: "c", 
} 

我怎樣才能獲得視頻(子對象)父產品裏面,這樣說:

{ 
    Product: { 
     id: "3", 
     video_id: "1", 
     Video: { 
     id: "1", 
     url: "c", 
     } 
} 

我知道,對於這個特殊的情況下,它很容易創建一個新的數組,因爲theres只有兩個對象,但無論如何,使這種自動更大的關係,可以cakephp處理這個?

+0

你scenraio是完全錯誤的。您不能將模型類放到其他模型中。閱讀更多信息:http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html和http://book.cakephp.org/2.0/en/models/retrieving-your-data .html –

+0

謝謝你的迴應。我展示的代碼只是僞代碼。在cakephp中,你需要建立關係,但是「hasone」和「belongs」存檔的內容的表示正是我所展現的。我需要這種表示(對象內部的對象),因爲我需要爲其他plataforms(android/ios)導出json,並且這些模型的默認archicteture是父內部的子對象。 – sagits

+0

在您的示例Product belongsTo Video中,因爲產品表具有外鍵。所以,產品是視頻的孩子,但反之亦然。 – bancer

回答

2

試試這種方法。覆蓋默認find('all'),以便它將接受自定義參數,這將允許重新格式化結果。把這個AppModel,因此它是所有車型訪問

編輯從評論要求從格式化結果移除HABTM協會空協會和聯合數據庫:

class AppModel extends Model 
{ 
    protected function _findAll($state, $query, $results = array()) 
    { 
     if ($state === 'before') { 
      return $query; 
     } 

     if (isset($query['reformat']) && $query['reformat'] === true) { 
      foreach ($results as &$_result) { 
       reset($_result); 
       $modelName = key($_result); 
       $modelPart = array_shift($_result); 

       if (!empty($query['filter']) && is_array($query['filter'])) { 
        $this->recursive_unset($_result, $query['filter']); 
       } 

       $_result = array(
        $modelName => array_merge($modelPart, $_result) 
       ); 
      } 
     } 

     return $results; 
    } 

    public function getHabtmKeys() { 
     $habtmKeys = array(); 
     // 1. level inspection 
     foreach ($this->hasAndBelongsToMany as $name) { 
      $habtmKeys[] = $name['with']; 
     } 
     // 2. level inspection 
     $allAsssoc = array_merge(
      $this->belongsTo, 
      $this->hasMany, 
      $this->hasOne 
     ); 
     foreach ($allAsssoc as $assocName => $assocVal) { 
      foreach ($this->$assocName->hasAndBelongsToMany as $name) { 
       $habtmKeys[] = $name['with']; 
      } 
     } 

     return $habtmKeys; 
    } 

    private function recursive_unset(&$array, $keys_to_remove) { 
     foreach ($keys_to_remove as $_key) { 
      unset($array[$_key]); 
     } 

     foreach ($array as $key => &$val) { 
      if (is_array($val)) { 
       if (empty($val) || (!isset($val[0]) && empty($val['id']))) { 
        unset($array[$key]); 
       } else { 
        $this->recursive_unset($val, $keys_to_remove); 
       } 
      } 
     } 
    } 
} 

要刪除空協會HABTM聯合數據,我使用recursive unset procedure加上檢查協會的相關型號。我無法通過配置查找,包含或任何其他方式來實現此目的。

接着array_shift($_result)劃分$_result陣列分爲兩個部分 - 在其上find已運行主模型(它總是在結果的第一密鑰)和其餘(所有關聯),然後將其合併下的這些陣列主要模型的關鍵。當然,這隻會在第一級重新格式化結果,但更深層次上的關聯是默認嵌套的,因此您不需要關心它。

一如既往地使用find('all'),但提供自定義reformatfilter參數。如果您不提供它們,結果將以默認格式提取。

  • filter是從結果

  • getHabtmKeys()動態將獲取模型(僅1和第2級協會HABTM協會鍵的陣列,可以被進一步修飾以甚至檢查除去鍵陣列更深)。

用法:

// To nest child associations in parent 
$this->Product->find('all', array(
    'reformat' => true 
)); 
// To remove also joint data for HABTM and empty associations 
$this->Product->find('all', array(
    'reformat' => true, 
    'filter' => $this->Product->getHabtmKeys(),   
)); 
// Keys to remove can be also manually added 
$this->Product->find('all', array(
    'reformat' => true, 
    'filter' => array_merge($this->Product->getHabtmKeys(), 'SomeExtraKey'), 
)); 

參見:Retrieving Your Data > Creating custom find types

+0

謝謝,它幾乎奏效。我已經嘗試銷售<產品<圖像。但產品(內部銷售)現在顯示一個空的銷售陣列(這一個我可以刪除,如果空,我猜),每個圖像顯示一個名爲「ProductsImage」這是hasmany表的名稱與products_images關聯的數組,我怎麼能刪除這個數組? – sagits

+0

@sagits我更新了我的答案,檢查出來,現在它也應該刪除額外的HABTM數據和空關聯。 –

+0

完美。順便說一下,我找到了一個插件,改變發現檢索對象,但我更喜歡你的方式,因爲該插件隱藏了一些默認功能,我將它添加到你的答案無論如何。感謝您的幫助。 – sagits

2

這將努力獲取每個產品的每個視頻的孩子在的findall

$products = $this->Product->find('all') 

foreach($products as $product) { 
    echo $product["Video"]["url"]; 
} 
+0

謝謝你的回答。在這個例子中,它很容易將一個數組推到另一個數組,我可以在$ product [「Product」]中放映$ product [「Video」]。但是,我必須在我所有的模型中手動執行此操作。我後爲自動爲我的所有模型做到這一點。 – sagits

2

的方式蛋糕返回對象是正確的,因爲它正在訪問參與並返回主查找對象中的數據。

如果您有更深的遞歸級別,或者您使用可容納來訪問更深的關係,則您正在談論的對象內部的對象會發生。

例如

$this->Product->find('all'); 

會回到像

array(
    'Product' => array(
    'id' => '3', 
    'video_id' => '1', 
), 
    'Video' => array(
    'id' => '1', 
    'url' => c, 
), 
) 

一個對象的對象佈局你的只有後發生的情況,如果有一個的hasMany或HABTM加入對型號,或者您更改級別或使用可容納來查看加入模型的關係。

我希望這是有道理的。

+0

感謝您的回答。但在hasmany和HABTM上它仍然顯示了2個獨立的數組(每個對象類型一個)。我可以使用可容納的產品在內部產品視頻陣列嗎?怎麼樣? – sagits