2010-09-11 33 views
14

Chỉ cần bắt đầu làm việc với Doctrine2 và tôi tự hỏi làm thế nào/nếu tôi có thể sử dụng một lớp sưu tập tùy chỉnh. Tìm kiếm chỉ cho tôi đến this part of the documentation:Bộ sưu tập tùy chỉnh trong Doctrine2

Trường và thuộc tính liên tục có giá trị bộ sưu tập phải được xác định theo giao diện Doctrine\Common\Collections\Collection. Loại triển khai bộ sưu tập có thể được ứng dụng sử dụng để khởi tạo các trường hoặc thuộc tính trước khi thực thể được thực hiện liên tục. Khi thực thể được quản lý (hoặc tách ra), quyền truy cập tiếp theo phải thông qua loại giao diện.

Mặc dù tôi chắc chắn nó rõ ràng với ai đó, tôi hơi mờ trên đó.

Nếu tôi thiết lập Pháp nhân của mình để khởi tạo (giả sử trong __construct()) biến thu thập cho một lớp thực hiện giao diện đúng - Doctrine2 sẽ tiếp tục sử dụng lớp đó làm bộ sưu tập không? Tôi có hiểu chính xác không?

Cập nhật: Ngoài ra, tôi thu thập từ nhiều chủ đề khác nhau mà đối tượng giữ chỗ được sử dụng trong tải chậm có thể ảnh hưởng đến cách sử dụng bộ sưu tập tùy chỉnh.

+1

Đối với những người đến đây để tìm câu trả lời: Tính đến thời điểm này, [tính năng] (https://github.com/doctrine/doctrine2/issues/5057) vẫn chưa được triển khai, vui lòng đóng góp trong chuỗi thảo luận tính năng (upvotes, trường hợp sử dụng, giải pháp của bạn). – Arkemlar

Trả lời

18

Hãy để tôi cố gắng làm rõ những gì có thể, không thể và được lên kế hoạch với các ví dụ.

Các trích dẫn từ cuốn hướng dẫn về cơ bản có nghĩa là bạn có thể có các loại thực hiện tùy chỉnh sau:

use Doctrine\Common\Collections\Collection; 

// MyCollection is the "implementation type" 
class MyCollection implements Collection { 
    // ... interface implementation 

    // This is not on the Collection interface 
    public function myCustomMethod() { ... } 
} 

Bây giờ bạn có thể sử dụng nó như sau:

class MyEntity { 
    private $items; 
    public function __construct() { 
     $this->items = new MyCollection; 
    } 
    // ... accessors/mutators ... 
} 

$e = new MyEntity; 
$e->getItems()->add(new Item); 
$e->getItems()->add(new Item); 
$e->getItems()->myCustomMethod(); // calling method on implementation type 

// $em instanceof EntityManager 
$em->persist($e); 

// from now on $e->getItems() may only be used through the interface type 

Nói cách khác, miễn là một thực thể là MỚI (không được quản lý, mở hoặc loại bỏ) bạn được tự do sử dụng loại triển khai cụ thể của các bộ sưu tập, ngay cả khi nó không đẹp. Nếu nó không phải là MỚI, bạn phải truy cập chỉ loại giao diện (và lý tưởng kiểu gợi ý trên nó). Điều đó có nghĩa là loại triển khai thực sự không quan trọng. Khi một cá thể MyEntity liên tục được lấy ra từ cơ sở dữ liệu, nó sẽ không sử dụng MyCollection (các hàm tạo không được Doctrine gọi, kể từ khi Doctrine chỉ tái tạo các đối tượng tồn tại/liên tục, nó không bao giờ tạo ra các đối tượng mới). Và kể từ khi một thực thể như vậy được quản lý, truy cập phải xảy ra thông qua các loại giao diện anyways.

Bây giờ cho những gì được lên kế hoạch. Cách đẹp hơn để có bộ sưu tập tùy chỉnh là cũng có loại giao diện tùy chỉnh, giả sử IMyCollection và MyCollection là loại triển khai.Sau đó, để làm cho nó hoạt động hoàn hảo với các dịch vụ kiên trì thuyết 2 bạn sẽ cần phải thực hiện một cài đặt tùy chỉnh PersistentCollection, nói, MyPersistentCollection mà trông như thế này:

class MyPersistentCollection implements IMyCollection { 
    // ... 
} 

Sau đó, bạn sẽ nói với Giáo lý trong các bản đồ để sử dụng MyPersistentCollection trình bao bọc cho bộ sưu tập đó (hãy nhớ, một PersistentCollection kết thúc tốt đẹp một loại triển khai bộ sưu tập, triển khai cùng một giao diện, để nó có thể thực hiện tất cả các công việc tồn tại trước/sau khi ủy nhiệm cho kiểu triển khai bộ sưu tập cơ bản).

Vì vậy, việc thực hiện bộ sưu tập tùy chỉnh sẽ bao gồm 3 phần:

  1. loại Interface
  2. loại thực hiện (thực hiện loại giao diện)
  3. dai dẳng loại wrapper (thực hiện loại giao diện)

Điều này sẽ không chỉ làm cho nó có thể viết các bộ sưu tập tùy chỉnh mà làm việc dường như với Doctrine 2 ORM mà còn để viết chỉ một loại trình bao bọc liên tục tùy chỉnh, cho e xample để tối ưu hóa hành vi tải/khởi tạo lười biếng của một bộ sưu tập cụ thể đối với các nhu cầu ứng dụng cụ thể.

Bạn chưa thể thực hiện việc này nhưng sẽ thực hiện được. Đây là cách thực sự thanh lịch và đầy đủ chức năng để viết và sử dụng các bộ sưu tập hoàn toàn tùy chỉnh tích hợp hoàn hảo trong lược đồ kiên trì trong suốt được cung cấp bởi Doctrine 2.

+0

Chi tiết tuyệt vời ở đây và được giải thích rất rõ. Làm rõ tài liệu rất nhiều cho tôi. – cantera

+0

Xin chào, bây giờ là 2 năm kể từ khi bạn viết rằng "nó được lên kế hoạch" nhưng như tôi thấy, nó vẫn không phải là. Bạn có bất kỳ đầu mối nào khi tính năng này có thể được triển khai không? – grongor

+0

+1 tự hỏi liệu/hy vọng rằng điều này đã được thực hiện chưa. Tôi đang trên Doctrine 2.3 nhưng không thấy bất kỳ dấu hiệu cho thấy cách tiếp cận này đã được kích hoạt. –

0

Không, bất cứ khi nào Doctrine cung cấp cho bạn trở lại thực hiện giao diện Doctrine \ Common \ Collections \ Collection, nó sẽ là một cá thể Doctrine \ ORM \ PersistentCollection. Bạn không thể đặt thêm logic tùy chỉnh vào bộ sưu tập. Tuy nhiên điều đó thậm chí không cần thiết.

Giả sử bạn có một thực thể (Đơn đặt hàng có nhiều OrderItems), thì phương pháp tính tổng số tiền không được đặt trên bộ sưu tập, nhưng trên mục Đơn đặt hàng. Vì đó là vị trí mà tổng có ý nghĩa trong mô hình miền của bạn:

class Order 
{ 
    private $items; 

    public function getTotalSum() 
    { 
     $total = 0; 
     foreach ($this->items AS $item) { 
      $total += $item->getSum(); 
     } 
     return $total; 
    } 
} 

Tuy nhiên, bộ sưu tập chỉ là các phần kỹ thuật của ORM, chúng giúp triển khai và quản lý tài liệu tham khảo giữa các đối tượng.

+0

Suy nghĩ chính của tôi là cung cấp thứ tự/sắp xếp/lọc, không chạy các phép tính trên các thực thể. –

+0

Ngay cả các phương pháp sắp xếp/lọc được đặt tốt nhất vào các thực thể giữ bộ sưu tập. Tuy nhiên, cũng có các phương thức chấp nhận bao đóng và thực hiện công việc cho bạn, ví dụ: $ collection-> map (function ($ element) {return $ element-> getProperty();}); – beberlei

+0

@beberlei Nhưng nếu nhiều thực thể có cùng một bộ sưu tập, bạn sẽ kết thúc mã trùng lặp (trừ khi bạn sử dụng các hàm ẩn danh). –

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