2015-04-18 21 views
7

Tôi có các bảng DB sau đây: các mục, người dùng, nhóm, itemImages. Có rất nhiều mối quan hệ giữa (mục, nhóm) và (người dùng, nhóm) và một đến nhiều giữa (mục, itemImages). Tất cả các khóa nước ngoài thích hợp đã được thiết lập trong CakePHP dưới dạng liên kết.CakePHP 3 có các trường chọn

Làm cách nào để tạo truy vấn có chứa() chọn tất cả các mục và hình ảnh chính của chúng trong nhóm được gán làm nhóm chính cho người dùng có id cụ thể?

Để làm cho nó rõ ràng hơn, đây là những gì một truy vấn SQL đơn giản sẽ như thế nào:

SELECT items.id AS itemId, items.name, itemImages.url AS itemUrl 
FROM items 
INNER JOIN groups_items ON groups_items.item_id = items.id 
INNER JOIN groups ON groups_images.group_id = groups.id 
INNER JOIN groups_users ON groups_users.group_id = groups.id 
INNER JOIN users ON groups_users.user_id = users.id 
INNER JOIN itemImages ON itemImages.item_id = items.id 
WHERE groups_users.isMainGroup = 1 
    AND users.id = :userId 
    AND itemImages.isMainImage = 1 

đang CakePHP Tôi có cho bây giờ:

$items = $this->Items->find() 
      ->hydrate(false) 
      ->contain([ 
       'Groups.Users' => function($q) use ($userId){ 
        return $q->where(['isMainGroup' => 1, 'Users.id' => $userId]); 
       }, 
       'ItemImages' => function($q){ 
        return $q->where(['isMainImage' => 1]); 
       }, 
      ]); 
      //->select(['itemId' => 'Items.id', 'Items.name', 'itemUrl' => 'itemImages.url']); 

Trả lời

9

khớp() phương pháp có thể giúp với này

$items = $this->Items->find() 
     ->hydrate(false) 
     ->select(['Items.id', 'Items.name', 'itemImages.url']) 
     ->distinct(['Items.id']) 
     ->matching('Groups.Users', function ($q) use ($userId) { 
      return $q->where(['Groups.isMainGroup' => 1, 'Users.id' => $userId]); 
     }) 
     ->matching('ItemImages', function ($q) { 
      return $q->where(['ItemImages.isMainImage' => 1]); 
     }) 
     ->contain([ 
      'ItemImages' => function ($q) { 
       return $q->autoFields(false) 
         ->select(['id','url']) 
         ->where(['ItemImages.isMainImage' => 1]); 
      } 
     ]); 

Tôi nghĩ, trong trường hợp này, con cuối cùng tuyên bố tain có thể được ommited, bởi vì kết quả mong muốn đã có trong _matchingData tài sản.

Lưu ý về distict() stament:

Như chức năng này sẽ tạo ra một INNER JOIN, bạn có thể muốn xem xét gọi riêng biệt trên các truy vấn tìm như bạn có thể nhận được hàng trùng lặp nếu điều kiện của bạn không lọc chúng đã

http://book.cakephp.org/3.0/en/orm/retrieving-data-and-resultsets.html#filtering-by-associated-data

+0

Vâng, cuối cùng chứa là không cần thiết - tất cả các dữ liệu đã alre ady trong _matchingData từ các hàm matching(). Câu hỏi lớn hơn của tôi là làm thế nào để "làm phẳng" kết quả đúng cách. Khi tôi chọn() như vậy, nó mang lại cho tôi url như một subobject dưới khóa "_matchingData", và tôi muốn nó ở cùng mức với các giá trị khác. Những gì tôi đã làm như một workaround là để json_encode -> loại bỏ tất cả "_matchingData." chuỗi xảy ra -> json_decode. – user1507558

+0

Nhận xét về câu lệnh 'khác biệt' rất hữu ích. –

Các vấn đề liên quan