2015-01-23 19 views
6

Có thể đặt mua bộ sưu tập quan hệ bằng một mảng ID riêng biệt trong khi vẫn truy cập thông qua mối quan hệ không?Sắp xếp Bộ sưu tập Laravel qua Array của ID

Cách cài đặt có Checklist có nhiều ChecklistItems, và tôi truy cập vào mối quan hệ này theo cách thông thường:

foreach ($list->items as $item) { 
    // More Code Here 
} 

Bây giờ thứ tự mong muốn của $item tồn tại như một tài sản trên $list dưới thuộc tính $list->item_order, nó chỉ là một mảng trong số $item ID theo thứ tự mong muốn của người dùng, cụ thể là $list đang được lặp lại.

Có cách nào khả thi để đặt hàng $items được đính kèm vào $list dựa trên mảng item_order mà mô hình $list có không?

(Tôi không thể chỉ thêm cột 'đơn đặt hàng' vào bảng 'mục', thay đổi đơn đặt hàng b/c dựa trên mối quan hệ 'danh sách' cụ thể).

Cảm ơn bạn đã trợ giúp!

+0

Tôi không biết làm thế nào bạn sẽ làm điều đó trong laravel, nhưng tôi biết rằng trong một truy vấn mysql thẳng nếu bạn muốn thứ gì đó được sắp xếp theo thứ tự được xác định trước bạn có thể sử dụng 'field' hoặc' find_in_set' như một phần của đặt hàng của bạn và chỉ liệt kê các giá trị theo bất kỳ thứ tự nào bạn muốn. Hoặc bạn có thể sử dụng một câu lệnh case trong select (hoặc order) trả về các số và thứ tự theo cột đó. Trừ khi laravel có cách khác, cách duy nhất tôi có thể nghĩ đến là lưu trữ các mục trong một mảng và sử dụng mảng id của bạn để có được thứ tự mong muốn. –

+0

@Matthew Brown '$ list-> item_order' được sắp xếp theo thứ tự các mục id? – voodoo417

+0

@ voodoo417 vâng, điều này là chính xác –

Trả lời

8

Bạn có thể làm điều này:

$order = $list->item_order; 
$list->items->sortBy(function($model) use ($order){ 
    return array_search($model->getKey(), $order); 
} 

Ngoài ra bạn có thể thêm một accessor thuộc tính để mô hình của bạn mà không giống nhau

public function getSortedItemsAttribute() 
{ 
    if (! is_null($this->item_order)) { 
     $order = $this->item_order; 

     $list = $this->items->sortBy(function($model) use ($order){ 
      return array_search($model->getKey(), $order); 
     }); 
     return $list; 
    } 
    return $this->items; 
} 

Cách sử dụng:

foreach ($list->sortedItems as $item) { 
    // More Code Here 
} 

Nếu bạn cần loại chức năng này trong nhiều nơi tôi đề xuất bạn tạo lớp Bộ sưu tập của riêng bạn:

class MyCollection extends Illuminate\Database\Eloquent\Collection { 

    public function sortByIds(array $ids){ 
     return $this->sortBy(function($model) use ($ids){ 
      return array_search($model->getKey(), $ids); 
     } 
    } 
} 

Sau đó, để thực sự sử dụng ghi đè lớp học newCollection() trong mô hình của bạn. Trong trường hợp này nó sẽ là trong lớp ChecklistItems:

public function newCollection(array $models = array()) 
{ 
    return new MyCollection($models); 
} 
+0

Tôi đã kết thúc bằng cách sử dụng phương pháp này, hoạt động tuyệt vời. Tôi không có ý tưởng chức năng sortBy cũng chấp nhận đóng cửa. –

1

Bạn có thể thử thiết lập một mối quan hệ đó sẽ trả về kết quả theo thứ tự mà bạn đang tìm kiếm. Bạn vẫn có thể háo hức tải mối quan hệ và có kết quả theo thứ tự được chỉ định. Tất cả điều này giả định trường item_order là danh sách các chuỗi được phân tách bằng dấu phẩy.

public function itemsOrdered() 
{ 
    /** 
    * Adds conditions to the original 'items' relationship. Due to the 
    * join, we must specify to only select the fields for the related 
    * table. Then, order by the results of the FIND_IN_SET function. 
    */ 
    return $this->items() 
     ->select('checklist_items.*') 
     ->join('checklists', 'checklist_items.checklist_id', '=', 'checklists.id') 
     ->orderByRaw('FIND_IN_SET(checklist_items.id, checklists.item_order)'); 
} 

Hoặc, nếu bạn không muốn hardcode các bảng/lĩnh vực:

public function itemsOrdered() 
{ 
    $orderField = 'item_order'; 

    $relation = $this->items(); 
    $parentTable = $relation->getParent()->getTable(); 
    $related = $relation->getRelated(); 
    $relatedTable = $related->getTable(); 

    return $relation 
     ->select($relatedTable.'.*') 
     ->join($parentTable, $relation->getForeignKey(), '=', $relation->getQualifiedParentKeyName()) 
     ->orderByRaw('FIND_IN_SET('.$related->getQualifiedKeyName().', '.$parentTable.'.'.$orderField.')'); 
} 

Bây giờ, bạn có thể:

$list = Checklist::with('items', 'itemsOrdered')->first(); 
var_export($list->item_order); 
var_export($list->items->lists('id')); 
var_export($list->itemsOrdered->lists('id')); 

Chỉ cần một lời cảnh báo: đây là mã khá thực nghiệm . Dường như làm việc với số lượng dữ liệu thử nghiệm nhỏ mà tôi có sẵn cho tôi, nhưng tôi đã không làm bất cứ điều gì như thế này trong một môi trường sản xuất. Ngoài ra, điều này chỉ được thử nghiệm trên mối quan hệ HasMany. Nếu bạn thử mã chính xác này trên một BelongsToMany hoặc bất cứ điều gì như thế, bạn sẽ có vấn đề.

+0

Cảm ơn bạn đã dành thời gian viết bài này cho tôi :) –

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