2013-05-23 39 views
8

Intoduction vấn đề:đối tượng lập bản đồ MongoDB (PHP)

các thực hành tốt nhất để xây dựng đối tượng class T của tôi là gì, khi tôi nhận được nó từ một MongoCursor::getNext()? Theo như nó đi, getNext() chức năng của một MongoCursor trả về với một array. Tôi muốn sử dụng kết quả từ thời điểm đó làm object loại T.

Tôi có nên viết phương thức khởi tạo của riêng mình cho loại T, chấp nhận array không? Có bất kỳ giải pháp chung nào cho điều này không, ví dụ: khi nhập T extends GG thực hiện công việc theo cách thông thường, đệ quy (đối với tài liệu lồng nhau).

Tôi mới làm quen với MongoDB và tôi muốn xây dựng bản đồ chung của riêng mình với giao diện đẹp mắt.

Bounty:

  • Đó là những phương pháp có thể, mô hình và đó sẽ phù hợp với các khái niệm về MongoDB được nhiều nhất từ ​​quan điểm của PHP.
+0

Nếu bạn giải thích thêm về loại câu trả lời bạn muốn chúng tôi có thể cung cấp một câu trả lời, tôi muốn viết mã cho bạn những gì bạn muốn? – Sammaye

+0

Bạn đang trình bày một cách tiếp cận mang tính xây dựng và hữu ích đối với tôi, và tôi đã học được nhiều về kỹ thuật và việc thực hiện của bạn. Cảm ơn vì điều đó! Ngoài ra, tôi mở ra bất kỳ cách tiếp cận nào khác ngoài đó, tôi sẵn sàng xem nó, nếu nó tồn tại. Tôi đang cố gắng khám phá tất cả các khả năng và các mẫu về vấn đề này. – Dyin

Trả lời

3

Câu trả lời này đã được viết lại.

Hầu hết người lập bản đồ dữ liệu hoạt động bằng cách biểu diễn một đối tượng trên mỗi lớp hoặc "mô hình" thường là thuật ngữ được đặt ra. Nếu bạn muốn cho phép nhiều lần truy cập thông qua một đối tượng duy nhất (ví dụ: $model->find()), nó thường bị demmed sao cho phương thức sẽ không thực sự trả về một thể hiện của chính nó mà thay vào đó là một mảng hoặc MongoCursor các lớp tải mong muốn vào không gian.

Mô hình như vậy thường được kết nối với "Active Record". Đây là phương pháp mà ORM, ODM và khung công tác sử dụng để giao tiếp với cơ sở dữ liệu theo cách này hay cách khác, không chỉ cho MongoDB mà còn cho SQL và bất kỳ cơ sở dữ liệu nào khác xảy ra để trồng lên (Cassandra, CouchDB v.v.).

Cần lưu ý rằng ngay cả khi bản ghi hoạt động cung cấp nhiều quyền lực, nó không được bỏ qua toàn bộ ứng dụng. Có những lúc sử dụng trình điều khiển trực tiếp sẽ mang lại nhiều lợi ích hơn. Hầu hết các ORM, ODM và khung công tác đều cung cấp khả năng truy cập trực tiếp vào trình điều khiển một cách nhanh chóng và dễ dàng vì lý do này.

Có nhiều người cho rằng, không có người lập bản đồ dữ liệu trọng lượng nhẹ. Nếu bạn định ánh xạ dữ liệu được trả về của bạn vào các lớp thì nó sẽ tiêu thụ tài nguyên, kết thúc. Lợi ích của việc này là sức mạnh bạn nhận được khi thao tác các đối tượng của bạn.

Bản ghi hoạt động thực sự tốt khi có thể cung cấp các sự kiện và trình kích hoạt từ bên trong PHP.Một ví dụ điển hình là của một ORM tôi thực hiện cho Yii: https://github.com/Sammaye/MongoYii nó có thể cung cấp móc cho:

  • afterConstruct
  • beforeFind
  • afterFind
  • beforeValidate
  • afterValidate
  • beforeSave
  • afterSave

Cần lưu ý rằng khi nói đến những sự kiện như beforeSaveafterSave MongoDB không có trigger (https://jira.mongodb.org/browse/SERVER-124) để nó có ý nghĩa rằng việc áp dụng nên xử lý này. Trên lý do rõ ràng cho ứng dụng xử lý điều này, nó cũng giúp xử lý tốt hơn các hàm tiết kiệm bằng cách có thể gọi các hàm PHP gốc của bạn để thao tác mọi tài liệu được lưu trước khi chạm vào cơ sở dữ liệu.

Hầu hết người lập bản đồ dữ liệu hoạt động bằng cách sử dụng CRUD lớp riêng của PHP để đại diện cho họ. Ví dụ để tạo ra một kỷ lục mới:

$d=new User(); 
$d->username='sammaye'; 
$d->save(); 

Đây là một cách tiếp cận khá tốt kể từ khi bạn tạo ra một "mới" (https://github.com/Sammaye/MongoYii/blob/master/EMongoDocument.php#L46 cho thấy làm thế nào tôi chuẩn bị cho một kỷ lục mới trong MongoYii) lớp để tạo ra một kỷ lục "mới". Nó khá phù hợp với ngữ nghĩa.

Chức năng cập nhật thường được truy cập thông qua chức năng đọc, bạn không thể cập nhật mô hình mà bạn không biết tồn tại. Điều này đưa chúng ta đến bước tiếp theo của các mô hình dân cư.

Để xử lý việc tạo mô hình ORM khác nhau, ODM và khung công tác cam kết với các phương pháp khác nhau. Ví dụ, phần mở rộng MongoYii của tôi sử dụng một phương thức nhà máy được gọi là model trong mỗi lớp để mang lại một thể hiện mới của chính nó để tôi có thể gọi số động findfindOne và các phương pháp khác.

Một số ORM, ODM và khung cung cấp chức năng đọc như các hàm trực tiếp static làm cho chúng trở thành phương thức nhà máy trong khi một số sử dụng mẫu đơn, tuy nhiên, tôi đã chọn không (https://stackoverflow.com/a/4596323/383478).

Hầu hết, nếu không phải tất cả, hãy triển khai một số dạng con trỏ. Điều này được sử dụng để trả về bội số của các mô hình và kết thúc trực tiếp (thông thường) MongoCursor để thay thế phương thức current() bằng cách trả về một mô hình được điền trước.

Ví dụ gọi:

User::model()->find(); 

Would return một EMongoCursor (trong MongoYii) mà sau đó sẽ sotre thực tế là lớp User đã được sử dụng để nhanh chóng các con trỏ và khi được gọi như:

foreach(User::model() as $k=>$v){ 
    var_dump($v); 
} 

Gọi phương thức current() tại đây: https://github.com/Sammaye/MongoYii/blob/master/EMongoCursor.php#L102 trả về một phiên bản mới của mô hình.

Có một số ORM, ODM và khung thực hiện tải mảng mong muốn.Điều này có nghĩa là họ sẽ tải toàn bộ kết quả thẳng vào RAM của bạn dưới dạng một loạt các mô hình. Cá nhân tôi không thích cách tiếp cận này, nó lãng phí và cũng không tốt khi bạn cần sử dụng bản ghi hoạt động cho bản cập nhật lớn hơn do thêm một số chức năng mới ở những nơi cần thêm vào bản ghi cũ.

Một chủ đề cuối cùng trước khi tôi tiếp tục là bản chất schemaless của MongoDB. Vấn đề với việc sử dụng các lớp PHP với MongoDB là bạn muốn tất cả các chức năng của PHP nhưng với tính chất biến của MongoDB. Điều này dễ dàng hơn trong SQL vì nó có một lược đồ được xác định trước, bạn chỉ cần truy vấn nó và các công việc đã làm; tuy nhiên, MongoDB không có thứ gì như vậy.

Điều này làm cho việc xử lý lược đồ trong MongoDB khá nguy hiểm. Hầu hết các ORM, ODM và khuôn khổ yêu cầu bạn xác định trước lược đồ tại chỗ (tức là Doctrine 2) sử dụng các biến số private với các phương thức getset. Trong MongoYii, để làm cho cuộc sống của tôi dễ dàng và thanh lịch, tôi quyết định giữ lại bản chất của MongoDBs bằng cách sử dụng các phép thuật có thể phát hiện (https://github.com/Sammaye/MongoYii/blob/master/EMongoModel.php#L26__gethttps://github.com/Sammaye/MongoYii/blob/master/EMongoModel.php#L47__set), nếu thuộc tính wa không thể truy cập được trong lớp, mảng nội bộ _attributes và nếu không thì chỉ cần trả lại null. Tương tự như vậy, để thiết lập một thuộc tính tôi sẽ chỉ đặt trong biến số _attributes bên trong.

Đối với giao dịch với cách chỉ định lược đồ này, tôi đã chuyển nhượng nội bộ cho người dùng, để xử lý các thuộc tính thiết lập từ biểu mẫu v.v. Tôi đã sử dụng quy tắc xác thực (https://github.com/Sammaye/MongoYii/blob/master/EMongoModel.php#L236) gọi hàm getSafeAttributeNames(). có quy tắc xác thực chống lại chúng. Nếu họ không có quy tắc xác thực thì các thuộc tính đó đã tồn tại trong mảng $_POST hoặc $_GET sắp tới sẽ không được đặt. Vì vậy, điều này cung cấp khả năng cho một lược đồ, nhưng an toàn, cấu trúc mô hình.

Vì vậy, chúng tôi đã đề cập đến cách thực sự sử dụng tài liệu gốc, bạn cũng hỏi cách người lập bản đồ dữ liệu xử lý các tài liệu phụ. Doctrine 2 và nhiều thứ khác cung cấp các subdocuments dựa trên lớp đầy đủ (http://docs.doctrine-project.org/projects/doctrine-mongodb-odm/en/latest/reference/embedded-mapping.html) nhưng điều này có thể cực kỳ tháo vát. Thay vào đó, tôi quyết định rằng tôi sẽ cung cấp các chức năng trợ giúp cho phép sử dụng linh hoạt subdocument mà không mong muốn tải chúng vào các mô hình và do đó tiêu thụ RAM. Về cơ bản những gì tôi đã làm là để lại cho họ khi họ là một cung cấp một validator (https://github.com/Sammaye/MongoYii/blob/master/validators/ESubdocumentValidator.php) để xác nhận bên trong của họ. Tất nhiên trình duyệt tính hợp lệ sẽ tự sinh ra nếu bạn có một quy tắc trong trình xác nhận hợp lệ đã sử dụng trình xác nhận hợp lệ một lần nữa để đưa ra một xác nhận hợp lệ của một tài liệu con lồng nhau thì nó sẽ hoạt động.

Vì vậy, tôi nghĩ hoàn thành một cuộc thảo luận rất cơ bản về ORM, ODM và khung sử dụng người lập bản đồ dữ liệu. Tất nhiên tôi có lẽ có thể viết toàn bộ một bài luận về điều này nhưng đây là một cuộc thảo luận đủ tốt cho phút tôi tin.

+0

Nếu bạn đang mở rộng 'MongoCursor', hơn' EMongoCursor' tại sao không 'mở rộng (s)' nó? '$ This-> partial' trong' getNext() 'là gì? Bạn nghĩ gì về phương pháp đó, khi bạn trao quyền cho 'T' thực sự giao tiếp với cơ sở dữ liệu, ví dụ:' $ t-> update() '? – Dyin

+0

@Dyin Tôi đặc biệt khuyên bạn không nên mở rộng đối tượng c của MongoCursor, nó luôn dẫn đến những điều xấu. '$ this-> partial' là một sai lầm, điều này thực sự được lấy từ Yii ORM của tôi và được sửa đổi thành độc lập.Đối với 'T' giao tiếp, tôi thực sự thực hiện hồ sơ hoạt động cho Yii theo mặc định, nếu bạn có thể hiểu nó ở đây là cơ sở mã: https://github.com/Sammaye/MongoYii và đây là một trong đó là chung chung hơn: https : //github.com/Sammaye/mongoglue – Sammaye

+0

Bạn có thể vui lòng, cải thiện câu trả lời của mình bằng cách thêm ghi chú về các quyết định của thiết kế và cách tiếp cận này không? Đây có phải là phiên bản nhẹ của mẫu Trình vẽ dữ liệu không? Có lẽ nhiều ví dụ sử dụng hơn sẽ tốt hơn để hiểu rõ hơn cách tiếp cận của bạn. – Dyin

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