MVC (Laravel) nơi thêm logic


136

Giả sử bất cứ khi nào tôi thực hiện thao tác CRUD hoặc sửa đổi mối quan hệ theo cách cụ thể tôi cũng muốn làm điều gì đó khác. Ví dụ, bất cứ khi nào ai đó xuất bản một bài đăng, tôi cũng muốn lưu một cái gì đó vào bảng để phân tích. Có thể không phải là ví dụ tốt nhất nhưng nói chung có rất nhiều chức năng "được nhóm" này.

Thông thường tôi thấy loại logic này được đưa vào bộ điều khiển. Đó là tất cả tốt đẹp cho đến khi bạn muốn tái tạo chức năng này ở nhiều nơi. Khi bạn bắt đầu tham gia vào các phần, việc tạo API và tạo nội dung giả, nó trở thành một vấn đề với việc giữ mọi thứ KHÔ.

Các cách tôi đã thấy để quản lý điều này là các sự kiện, kho lưu trữ, thư viện và thêm vào các mô hình. Dưới đây là những hiểu biết của tôi về mỗi:

Dịch vụ: Đây là nơi mà hầu hết mọi người có thể sẽ đặt mã này. Vấn đề chính của tôi với các dịch vụ là đôi khi thật khó để tìm thấy chức năng cụ thể trong chúng và tôi cảm thấy như chúng bị lãng quên khi mọi người tập trung vào sử dụng Eloquent. Làm thế nào tôi biết tôi cần gọi một phương thức publishPost()trong thư viện khi tôi có thể làm được $post->is_published = 1?

Điều kiện duy nhất tôi thấy điều này hoạt động tốt là nếu bạn CHỈ sử dụng các dịch vụ (và lý tưởng nhất là làm cho Eloquent không thể truy cập bằng cách nào đó từ tất cả các bộ điều khiển cùng nhau).

Cuối cùng, có vẻ như điều này sẽ tạo ra một loạt các tệp không cần thiết nếu các yêu cầu của bạn thường tuân theo cấu trúc mô hình của bạn.

Kho lưu trữ: Theo những gì tôi hiểu thì về cơ bản nó giống như một dịch vụ nhưng có giao diện để bạn có thể chuyển đổi giữa các ORM mà tôi không cần.

Sự kiện: Tôi thấy đây là hệ thống thanh lịch nhất theo nghĩa vì bạn biết các sự kiện mô hình của bạn sẽ luôn được gọi theo phương thức Eloquent, vì vậy bạn có thể viết bộ điều khiển của mình như bình thường. Tôi có thể thấy những điều này trở nên lộn xộn và nếu bất cứ ai có ví dụ về các dự án lớn sử dụng các sự kiện cho khớp nối quan trọng tôi muốn xem nó.

Mô hình: Theo truyền thống, tôi có các lớp thực hiện CRUD và cũng xử lý khớp nối quan trọng. Điều này thực sự làm mọi thứ trở nên dễ dàng bởi vì bạn biết tất cả các chức năng xung quanh CRUD + bất cứ điều gì phải được thực hiện với nó ở đó.

Đơn giản, nhưng trong kiến ​​trúc MVC, đây không phải là điều tôi thường làm. Theo một nghĩa nào đó mặc dù tôi thích điều này hơn các dịch vụ vì nó dễ tìm hơn một chút và có ít tệp để theo dõi hơn. Nó có thể có một chút vô tổ chức mặc dù. Tôi muốn nghe những nhược điểm của phương pháp này và tại sao hầu hết mọi người dường như không làm điều đó.

Những ưu điểm / nhược điểm của từng phương pháp là gì? Tui bỏ lỡ điều gì vậy?


3
Bạn có thể giảm thiểu câu hỏi của bạn?
Alpha

3
Ngoài ra bạn có thể kiểm tra điều này .
Alpha

1
"Làm sao tôi biết tôi cần gọi một phương thức PublishPost () trong thư viện khi tôi chỉ có thể thực hiện $ post-> is_published = 1?" Tài liệu?
ceejayoz

một trong những người đẹp về tài hùng biện và ORMS là làm việc với họ dễ dàng hơn mà không cần nhiều tài liệu?
Sabrina Leggett

1
Cảm ơn đã đăng bài này. Tôi đang đấu tranh với các vấn đề tương tự và tìm thấy bài viết và câu trả lời của bạn rất hữu ích. Cuối cùng, tôi đã quyết định rằng Laravel không cung cấp một kiến ​​trúc tốt cho bất cứ thứ gì trải dài ngoài một trang web Ruby-on-Rails nhanh chóng và bẩn thỉu. Trates ở khắp mọi nơi, khó khăn trong việc tìm kiếm các lớp chức năng và hàng tấn rác tự động ma thuật ở khắp mọi nơi. ORM chưa bao giờ hoạt động và nếu bạn đang sử dụng nó, có lẽ bạn nên sử dụng NoQuery.
Alex Barker

Câu trả lời:


171

Tôi nghĩ rằng tất cả các mẫu / kiến ​​trúc mà bạn trình bày đều rất hữu ích miễn là bạn tuân theo RẮN nguyên tắc .

Đối với vị trí để thêm logic, tôi nghĩ rằng điều quan trọng là phải tham khảo Nguyên tắc Trách nhiệm duy nhất . Ngoài ra, câu trả lời của tôi cho rằng bạn đang làm việc trong một dự án vừa / lớn. Nếu đó là một dự án ném một cái gì đó trên trang , hãy quên câu trả lời này và thêm tất cả vào bộ điều khiển hoặc mô hình.

Câu trả lời ngắn gọn là: Trường hợp có ý nghĩa với bạn (với các dịch vụ) .

Câu trả lời dài:

Kiểm soát viên : Trách nhiệm của Kiểm soát viên là gì? Chắc chắn, bạn có thể đặt tất cả logic của mình vào bộ điều khiển, nhưng đó có phải là trách nhiệm của bộ điều khiển không? Tôi không nghĩ vậy.

Đối với tôi, bộ điều khiển phải nhận được yêu cầu và trả về dữ liệu và đây không phải là nơi để xác thực, gọi các phương thức db, v.v.

Mô hình : Đây có phải là nơi tốt để thêm logic như gửi email chào mừng khi người dùng đăng ký hoặc cập nhật số phiếu bầu của bài đăng không? Điều gì nếu bạn cần gửi cùng một email từ một nơi khác trong mã của bạn? Bạn có tạo một phương thức tĩnh không? Nếu email đó cần thông tin từ một mô hình khác thì sao?

Tôi nghĩ rằng mô hình nên đại diện cho một thực thể. Với Laravel, tôi chỉ sử dụng lớp mô hình để thêm những thứ như fillable, guarded, tablevà các mối quan hệ (điều này là bởi vì tôi sử dụng Pattern Repository, nếu không thì mô hình cũng sẽ có save, update, findphương pháp, vv).

Kho lưu trữ (Mẫu lưu trữ) : Lúc đầu tôi rất bối rối vì điều này. Và, giống như bạn, tôi nghĩ "tốt, tôi sử dụng MySQL và đó là điều đó."

Tuy nhiên, tôi đã cân bằng giữa ưu và nhược điểm của việc sử dụng Mẫu lưu trữ và bây giờ tôi sử dụng nó. Tôi nghĩ rằng bây giờ , tại thời điểm này, tôi sẽ chỉ cần sử dụng MySQL. Nhưng, nếu ba năm kể từ bây giờ tôi cần thay đổi thành thứ gì đó như MongoDB, hầu hết công việc đã hoàn thành. Tất cả đều phải trả giá bằng một giao diện phụ và a $app->bind(«interface», «repository»).

Sự kiện ( Mẫu quan sát ): Sự kiện rất hữu ích cho những thứ có thể được ném ở bất kỳ lớp nào vào bất kỳ thời điểm nào. Ví dụ, hãy suy nghĩ về việc gửi thông báo cho người dùng. Khi bạn cần, bạn kích hoạt sự kiện để gửi thông báo tại bất kỳ lớp nào trong ứng dụng của bạn. Sau đó, bạn có thể có một lớp như thế UserNotificationEventsxử lý tất cả các sự kiện bị bắn của bạn cho thông báo người dùng.

Dịch vụ : Cho đến bây giờ, bạn có lựa chọn thêm logic vào bộ điều khiển hoặc mô hình. Đối với tôi, việc thêm logic trong Dịch vụ là điều hợp lý . Hãy đối mặt với nó, Dịch vụ là một cái tên lạ mắt cho các lớp học. Và bạn có thể có nhiều lớp như nó có ý nghĩa với bạn trong ứng dụng của bạn.

Lấy ví dụ này: Cách đây không lâu, tôi đã phát triển một cái gì đó giống như Google Forms. Tôi bắt đầu với một CustomFormServicevà kết thúc với CustomFormService, CustomFormRender, CustomFieldService, CustomFieldRender, CustomAnswerServiceCustomAnswerRender. Tại sao? Bởi vì nó có ý nghĩa với tôi. Nếu bạn làm việc với một nhóm, bạn nên đặt logic của mình vào nơi có ý nghĩa với nhóm.

Ưu điểm của việc sử dụng Dịch vụ so với Bộ điều khiển / Mô hình là bạn không bị ràng buộc bởi một Bộ điều khiển hoặc một Mô hình duy nhất. Bạn có thể tạo nhiều dịch vụ như cần thiết dựa trên thiết kế và nhu cầu của ứng dụng của bạn. Thêm vào đó là lợi thế của việc gọi Dịch vụ trong bất kỳ lớp nào trong ứng dụng của bạn.

Điều này kéo dài, nhưng tôi muốn cho bạn thấy cách tôi đã cấu trúc ứng dụng của mình:

app/
    controllers/
    MyCompany/
        Composers/
        Exceptions/
        Models/
        Observers/
        Sanitizers/
        ServiceProviders/
        Services/
        Validators/
    views
    (...)

Tôi sử dụng mỗi thư mục cho một chức năng cụ thể. Ví dụ, Validatorsthư mục chứa một BaseValidatorlớp chịu trách nhiệm xử lý xác nhận, dựa trên $rules$messagescác trình xác nhận cụ thể (thường là một cho mỗi mô hình). Tôi có thể dễ dàng đặt mã này trong Dịch vụ, nhưng thật hợp lý khi tôi có một thư mục cụ thể cho việc này ngay cả khi nó chỉ được sử dụng trong dịch vụ (hiện tại).

Tôi khuyên bạn nên đọc các bài viết sau, vì chúng có thể giải thích mọi thứ tốt hơn cho bạn:

Breaking the Mold by Dayle Rees (tác giả của CodeBright): Đây là nơi tôi kết hợp tất cả lại, mặc dù tôi đã thay đổi một vài thứ để phù hợp với nhu cầu của mình.

Phân tách mã của bạn trong Laravel bằng cách sử dụng Kho lưu trữ và Dịch vụ của Chris Goosey: Bài đăng này giải thích rõ Dịch vụ và Mẫu lưu trữ là gì và cách chúng khớp với nhau.

Laracasts cũng có Kho lưu trữ Đơn giản hóaTrách nhiệm duy nhất là các tài nguyên tốt với các ví dụ thực tế (mặc dù bạn phải trả tiền).


3
giải thích tuyệt vời. Đây là lúc tôi đang đứng - trong dự án hiện tại tôi đang đưa logic kinh doanh của mình vào các mô hình và nó thực sự hoạt động rất tốt. Chúng tôi chắc chắn cần phải loại bỏ RẮN một chút, nhưng, nó thực sự chưa khiến chúng tôi gặp rắc rối. Nó nhanh, hơi bẩn, nhưng cho đến nay dự án của chúng tôi rất dễ bảo trì vì nó quá KHÔ. Tôi chắc chắn ổn với việc gắn bó với họ tại thời điểm này bởi vì họ đã hoàn thành công việc, nhưng trong bất kỳ dự án nào trong tương lai, có lẽ tôi sẽ chỉ đi với bất cứ điều gì là tiêu chuẩn, có vẻ như các kho lưu trữ đã trở thành.
Sabrina Leggett

2
Tôi rất vui vì bạn đã tìm thấy một cách có ý nghĩa với bạn. Chỉ cần cẩn thận với các giả định mà bạn thực hiện ngày hôm nay . Tôi đã làm việc trong một dự án trong hơn 3 năm và kết thúc với các bộ điều khiển và mô hình với hơn 5000 dòng mã. Chúc may mắn với dự án của bạn.
Luís Cruz

cũng hơi bẩn nhưng tôi đã suy nghĩ về việc sử dụng các đặc điểm để tránh các mô hình trở nên khổng lồ. Bằng cách đó tôi có thể tách chúng ra một chút
Sabrina Leggett

Bài viết này nói rõ rằng KHI sử dụng dịch vụ có ý nghĩa. Trong ví dụ về Biểu mẫu của bạn, việc sử dụng các dịch vụ là hợp lý, nhưng anh ta nói rõ cách anh ta thực hiện nó, đó là khi logic liên quan trực tiếp đến một mô hình mà anh ta đặt nó trong mô hình đó. justinweiss.com/articles/where-do-you-put-your-code
Sabrina Leggett

Tôi thực sự thích lời giải thích. Có một câu hỏi tôi có: bạn đã đề cập không đưa xác nhận vào bộ điều khiển, vậy bạn nghĩ đâu là nơi tốt nhất để thực hiện xác nhận? Nhiều người đề nghị đưa nó vào lớp Yêu cầu mở rộng (và cả những gì chúng tôi hiện đang làm), nhưng nếu tôi không chỉ muốn xác thực theo yêu cầu http, mà còn trên lệnh thủ công, v.v., đó có thực sự là một nơi tốt không?
kingshark

24

Tôi muốn gửi một câu trả lời cho câu hỏi của riêng tôi. Tôi có thể nói về điều này trong nhiều ngày, nhưng tôi sẽ cố gắng đăng nó nhanh để đảm bảo tôi sẽ nhận được nó.

Cuối cùng tôi đã sử dụng cấu trúc hiện có mà Laravel cung cấp, nghĩa là tôi giữ các tệp của mình chủ yếu dưới dạng Mô hình, Chế độ xem và Trình điều khiển. Tôi cũng có một thư mục Thư viện cho các thành phần có thể tái sử dụng không thực sự là mô hình.

TÔI KHÔNG VIẾT MÔ HÌNH CỦA TÔI TRONG DỊCH VỤ / NHIỆM VỤ . Tất cả các lý do được cung cấp đã không thuyết phục 100% cho tôi về lợi ích của việc sử dụng dịch vụ. Mặc dù tôi có thể sai, theo như tôi có thể thấy chúng chỉ dẫn đến hàng tấn tệp gần như trống mà tôi cần tạo và chuyển đổi giữa khi làm việc với các mô hình và cũng thực sự làm giảm lợi ích của việc sử dụng hùng biện (đặc biệt là khi nói đến các mô hình RETRIEVING , ví dụ: sử dụng phân trang, phạm vi, v.v.).

Tôi đặt logic kinh doanh vào các MÔ HÌNH và truy cập hùng hồn trực tiếp từ bộ điều khiển của mình. Tôi sử dụng một số cách tiếp cận để đảm bảo rằng logic nghiệp vụ không bị bỏ qua:

  • Người truy cập và người đột biến: Laravel có người truy cập và người đột biến tuyệt vời. Nếu tôi muốn thực hiện một hành động bất cứ khi nào một bài đăng được chuyển từ bản nháp sang xuất bản, tôi có thể gọi đây là bằng cách tạo hàm setIsPublishedAttribution và bao gồm logic trong đó
  • Ghi đè Tạo / Cập nhật, v.v.: Bạn luôn có thể ghi đè các phương thức Eloquent trong các mô hình của mình để bao gồm chức năng tùy chỉnh. Bằng cách đó bạn có thể gọi chức năng trên bất kỳ hoạt động CRUD nào. Chỉnh sửa: Tôi nghĩ rằng có một lỗi với ghi đè tạo trong các phiên bản Laravel mới hơn (vì vậy tôi sử dụng các sự kiện hiện đã đăng ký trong boot)
  • Xác thực: Tôi kết nối xác thực của mình theo cùng một cách, ví dụ: Tôi sẽ chạy xác thực bằng cách ghi đè các hàm CRUD và cả trình truy cập / trình biến đổi nếu cần. Xem Esensi hoặc dwightwatson / xác nhận để biết thêm thông tin.
  • Phương thức ma thuật: Tôi sử dụng các phương thức __get và __set của các mô hình của mình để kết nối với chức năng khi thích hợp
  • Mở rộng Eloquent: Nếu có một hành động bạn muốn thực hiện trên tất cả các cập nhật / tạo, bạn thậm chí có thể mở rộng hùng hồn và áp dụng nó cho nhiều mô hình.
  • Sự kiện: Đây là một hướng thẳng và thường được thỏa thuận để làm điều này là tốt. Hạn chế lớn nhất với các sự kiện tôi nghĩ là các trường hợp ngoại lệ khó theo dõi (có thể không phải là trường hợp mới với hệ thống sự kiện mới của Laravel). Tôi cũng thích nhóm các sự kiện của mình theo những gì chúng làm thay vì khi chúng được gọi ... ví dụ: có một thuê bao MailSender lắng nghe các sự kiện gửi thư.
  • Thêm các sự kiện Pivot / BelongsToMany: Một trong những điều tôi đấu tranh lâu nhất là làm thế nào để gắn hành vi với việc sửa đổi các mối quan hệ thuộc sở hữu. Ví dụ, thực hiện một hành động bất cứ khi nào người dùng tham gia một nhóm. Tôi gần như đã hoàn thành việc đánh bóng một thư viện tùy chỉnh cho việc này. Tôi chưa xuất bản nó nhưng nó là chức năng! Sẽ cố gắng để gửi một liên kết sớm.EDIT Tôi đã kết thúc việc biến tất cả các trụ của mình thành các mô hình bình thường và cuộc sống của tôi đã dễ dàng hơn rất nhiều ...

Giải quyết mối quan tâm của mọi người với việc sử dụng các mô hình:

  • Cơ quan: Có nếu bạn bao gồm nhiều logic hơn trong các mô hình, chúng có thể dài hơn, nhưng nói chung tôi đã tìm thấy 75% các mô hình của tôi vẫn còn khá nhỏ. Nếu tôi chọn tổ chức những cái lớn hơn, tôi có thể thực hiện bằng các đặc điểm (ví dụ: tạo thư mục cho mô hình với một số tệp khác như PostScopes, PostAccessors, PostValidation, v.v. nếu cần). Tôi biết điều này không nhất thiết là những đặc điểm dành cho nhưng hệ thống này hoạt động mà không có vấn đề.

Ghi chú bổ sung: Tôi cảm thấy việc bọc các mô hình của bạn trong các dịch vụ giống như có một con dao quân đội Thụy Sĩ, với rất nhiều công cụ và xây dựng một con dao khác xung quanh nó mà về cơ bản cũng làm điều tương tự? Vâng, đôi khi bạn có thể muốn loại bỏ một lưỡi dao hoặc đảm bảo hai lưỡi dao được sử dụng cùng nhau ... nhưng thường có những cách khác để làm điều đó ...

KHI SỬ DỤNG DỊCH VỤ : Bài viết này nêu rất rõ các ví dụ TUYỆT VỜI khi nào nên sử dụng dịch vụ ( gợi ý: không thường xuyên lắm ). Ông nói về cơ bản khi đối tượng của bạn sử dụng nhiều mô hình hoặc mô hình tại các phần lạ trong vòng đời của chúng, điều đó có ý nghĩa. http://www.justinweiss.com/articles/where-do-you-put-your-code/


2
Những suy nghĩ thú vị và hợp lệ. Nhưng tôi tò mò - làm thế nào để bạn kiểm tra logic kinh doanh của mình nếu nó được gắn với các mô hình được gắn với Eloquent, được gắn với cơ sở dữ liệu?
JustAMartin

code.tutsplus.com/tutorials/ trên hoặc bạn có thể sử dụng các sự kiện như tôi đã nói nếu bạn muốn chia nhỏ hơn nữa
Sabrina Leggett

1
@JustAMartin bạn có chắc chắn rằng bạn không thể chỉ sử dụng cơ sở dữ liệu trong các bài kiểm tra đơn vị của mình không? Lý do không làm điều đó là gì? Nhiều người đồng ý rằng thường sử dụng cơ sở dữ liệu trong các bài kiểm tra đơn vị là được. (bao gồm Martin Fowler, martinfowler.com/bliki/UnitTest.html : "Tôi không coi việc sử dụng gấp đôi cho các tài nguyên bên ngoài như một quy tắc tuyệt đối. Nếu nói chuyện với tài nguyên là ổn định và đủ nhanh cho bạn thì không có lý do gì để không làm nó trong bài kiểm tra đơn vị của bạn ")
Alex P.

@ AlexP11223 Vâng, điều đó có ý nghĩa. Tôi đã cố gắng tích hợp SQLite làm cơ sở dữ liệu thử nghiệm của mình và nói chung nó đã hoạt động tốt, mặc dù SQLite có một số hạn chế nghiêm trọng phải tính đến trong quá trình di chuyển và truy vấn tùy chỉnh của Laravel (nếu có). Tất nhiên, những người sau đó không hoàn toàn kiểm tra đơn vị mà là kiểm tra chức năng, nhưng nó thậm chí còn hiệu quả hơn theo cách đó. Tuy nhiên, nếu bạn muốn kiểm tra mô hình của mình một cách tách biệt hoàn toàn (như một thử nghiệm đơn vị nghiêm ngặt), nó có thể yêu cầu số lượng mã bổ sung đáng chú ý (giả, v.v.).
JustAMartin

22

Những gì tôi sử dụng để làm logic giữa các bộ điều khiển và mô hình là tạo một lớp dịch vụ . Về cơ bản, đây là luồng của tôi cho bất kỳ hành động nào trong ứng dụng của tôi:

  1. Trình điều khiển nhận hành động được yêu cầu của người dùng và gửi các tham số và ủy quyền mọi thứ cho một lớp dịch vụ.
  2. Lớp dịch vụ thực hiện tất cả các logic liên quan đến hoạt động: xác thực đầu vào, ghi nhật ký sự kiện, hoạt động cơ sở dữ liệu, v.v ...
  3. Mô hình chứa thông tin về các trường, chuyển đổi dữ liệu và định nghĩa về xác nhận thuộc tính.

Đây là cách tôi làm điều đó:

Đây là phương pháp của bộ điều khiển để tạo ra một cái gì đó:

public function processCreateCongregation()
{
    // Get input data.
    $congregation                 = new Congregation;
    $congregation->name           = Input::get('name');
    $congregation->address        = Input::get('address');
    $congregation->pm_day_of_week = Input::get('pm_day_of_week');
    $pmHours                      = Input::get('pm_datetime_hours');
    $pmMinutes                    = Input::get('pm_datetime_minutes');
    $congregation->pm_datetime    = Carbon::createFromTime($pmHours, $pmMinutes, 0);

    // Delegates actual operation to service.
    try
    {
        CongregationService::createCongregation($congregation);
        $this->success(trans('messages.congregationCreated'));
        return Redirect::route('congregations.list');
    }
    catch (ValidationException $e)
    {
        // Catch validation errors thrown by service operation.
        return Redirect::route('congregations.create')
            ->withInput(Input::all())
            ->withErrors($e->getValidator());
    }
    catch (Exception $e)
    {
        // Catch any unexpected exception.
        return $this->unexpected($e);
    }
}

Đây là lớp dịch vụ thực hiện logic liên quan đến hoạt động:

public static function createCongregation(Congregation $congregation)
{
    // Log the operation.
    Log::info('Create congregation.', compact('congregation'));

    // Validate data.
    $validator = $congregation->getValidator();

    if ($validator->fails())
    {
        throw new ValidationException($validator);
    }

    // Save to the database.
    $congregation->created_by = Auth::user()->id;
    $congregation->updated_by = Auth::user()->id;

    $congregation->save();
}

Và đây là mô hình của tôi:

class Congregation extends Eloquent
{
    protected $table = 'congregations';

    public function getValidator()
    {
        $data = array(
            'name' => $this->name,
            'address' => $this->address,
            'pm_day_of_week' => $this->pm_day_of_week,
            'pm_datetime' => $this->pm_datetime,
        );

        $rules = array(
            'name' => ['required', 'unique:congregations'],
            'address' => ['required'],
            'pm_day_of_week' => ['required', 'integer', 'between:0,6'],
            'pm_datetime' => ['required', 'regex:/([01]?[0-9]|2[0-3]):[0-5]?[0-9]:[0-5][0-9]/'],
        );

        return Validator::make($data, $rules);
    }

    public function getDates()
    {
        return array_merge_recursive(parent::getDates(), array(
            'pm_datetime',
            'cbs_datetime',
        ));
    }
}

Để biết thêm thông tin về cách này, tôi sử dụng để sắp xếp mã của mình cho ứng dụng Laravel: https://github.com/rmariuzzo/Pitimi


Có vẻ như các dịch vụ là những gì tôi gọi là thư viện trong bài viết của mình. Tôi nghĩ rằng điều này tốt hơn kho lưu trữ nếu bạn không cần sử dụng nhiều ORMS, nhưng vấn đề là bạn phải di chuyển toàn bộ dự án của mình (điều mà bạn không phải làm với các sự kiện) và có vẻ như cuối cùng chỉ phản ánh cấu trúc Mô hình để bạn có tất cả các tệp bổ sung này. Tại sao không chỉ đưa nó vào các mô hình? Ít nhất theo cách đó bạn không có các tập tin bổ sung.
Sabrina Leggett

Đó là một câu hỏi thú vị @SabrinaGelbart, tôi đã được dạy để cho các mô hình đại diện cho các thực thể cơ sở dữ liệu và không giữ bất kỳ logic nào. Đó là lý do tôi tạo ra các tệp bổ sung có tên là dịch vụ: để giữ tất cả logic và mọi hoạt động bổ sung. Tôi không chắc toàn bộ ý nghĩa của các sự kiện bạn đã mô tả trước đây là gì, nhưng tôi nghĩ với các dịch vụ và sử dụng các sự kiện của Laravel, chúng tôi có thể tạo ra tất cả các phương thức dịch vụ để thực hiện các sự kiện khi bắt đầu và kết thúc. Bằng cách này, bất kỳ sự kiện có thể được tách rời hoàn toàn khỏi logic. Bạn nghĩ sao?
Rubens Mariuzzo

Tôi đã được dạy rằng quá về các mô hình ... sẽ rất tốt để có được một lời giải thích tốt cho lý do tại sao (có thể các vấn đề phụ thuộc)?
Sabrina Leggett

Tôi thích cách tiếp cận này! Tôi đã tìm kiếm trên internet để có ý tưởng về cách tôi nên xử lý logic của mô hình, xem qua Kho lưu trữ nhưng có vẻ quá phức tạp và vô dụng đối với một chút sử dụng. Dịch vụ là một ý tưởng tốt. Câu hỏi của tôi là sau khi tạo một thư mục Dịch vụ trong thư mục ứng dụng, bạn có phải đưa nó vào bootstrap / start.php hoặc bất cứ nơi nào để khởi động không vì tôi đã xem qua git của bạn không thể tìm thấy nó? @RubensMariuzzo. Nó tự động trở nên có sẵn ứng dụng? vì vậy chúng tôi chỉ có thể sử dụng CongregationService :: getCongregations (); ??
Oguzhan

1
Nếu tất cả những gì bạn đang làm là $congregation->save();có lẽ bạn sẽ không cần Kho lưu trữ. Tuy nhiên, bạn có thể thấy nhu cầu truy cập dữ liệu của mình tăng theo thời gian. Bạn có thể bắt đầu có nhu cầu cho $congregation->destroyByUser()hoặc$congregationUsers->findByName($arrayOfSelectedFields); vân vân. Tại sao không tách đôi dịch vụ của bạn khỏi nhu cầu truy cập dữ liệu. Để phần còn lại của ứng dụng của bạn hoạt động với các đối tượng / mảng được trả về từ repos và chỉ cần xử lý thao tác / định dạng / v.v ... Repo của bạn sẽ phát triển (nhưng chia chúng thành các tệp khác nhau, cuối cùng là sự phức tạp của dự án phải nằm ở đâu đó).
prograhammer

12

Theo tôi, Laravel đã có nhiều tùy chọn để bạn lưu trữ logic kinh doanh của mình.

Câu trả lời ngắn:

  • Sử dụng Requestcác đối tượng của laravel để tự động xác thực đầu vào của bạn và sau đó duy trì dữ liệu trong yêu cầu (tạo mô hình). Vì tất cả các đầu vào của người dùng đều có sẵn trực tiếp trong yêu cầu, tôi tin rằng việc thực hiện điều này ở đây là hợp lý.
  • Sử dụng Jobcác đối tượng của laravel để thực hiện các nhiệm vụ yêu cầu các thành phần riêng lẻ, sau đó chỉ cần gửi chúng đi. Tôi nghĩ rằng Jobcác lớp dịch vụ bao gồm. Họ thực hiện một nhiệm vụ, chẳng hạn như logic kinh doanh.

Câu trả lời dài (er):

Sử dụng các vị trí khi được yêu cầu: Các kho lưu trữ bị ràng buộc bị che lấp, và hầu hết thời gian, chỉ đơn giản được sử dụng như một accessormô hình. Tôi cảm thấy như họ chắc chắn có một số sử dụng, nhưng trừ khi bạn đang phát triển một ứng dụng lớn đòi hỏi mức độ linh hoạt đó để bạn có thể bỏ hoàn toàn laravel, hãy tránh xa các kho lưu trữ. Bạn sẽ cảm ơn chính mình sau này và mã của bạn sẽ thẳng hơn nhiều.

Hãy tự hỏi mình xem có khả năng bạn sẽ thay đổi các khung công tác PHP hoặc sang loại cơ sở dữ liệu mà laravel không hỗ trợ không.

Nếu câu trả lời của bạn là "Có thể là không", thì đừng triển khai mẫu kho lưu trữ.

Ngoài ra, vui lòng không đặt một mẫu lên trên một ORM tuyệt vời như Eloquent. Bạn chỉ cần thêm sự phức tạp không cần thiết và nó sẽ không có lợi cho bạn.

Sử dụng các dịch vụ một cách tiết kiệm: Các lớp dịch vụ đối với tôi, chỉ là nơi lưu trữ logic kinh doanh để thực hiện một nhiệm vụ cụ thể với các phụ thuộc nhất định. Laravel có những thứ này, được gọi là 'Việc làm' và chúng có tính linh hoạt cao hơn nhiều so với lớp Dịch vụ tùy chỉnh.

Tôi cảm thấy như Laravel có một giải pháp toàn diện cho MVCvấn đề logic. Đó chỉ là một vấn đề hoặc tổ chức.

Thí dụ:

Yêu cầu :

namespace App\Http\Requests;

use App\Post;
use App\Jobs\PostNotifier;
use App\Events\PostWasCreated;
use App\Http\Requests\Request;

class PostRequest extends Request
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'title'       => 'required',
            'description' => 'required'
        ];
    }

    /**
     * Save the post.
     *
     * @param Post $post
     *
     * @return bool
     */
    public function persist(Post $post)
    {
        if (!$post->exists) {
            // If the post doesn't exist, we'll assign the
            // post as created by the current user.
            $post->user_id = auth()->id();
        }

        $post->title = $this->title;
        $post->description = $this->description;

        // Perform other tasks, maybe fire an event, dispatch a job.

        if ($post->save()) {
            // Maybe we'll fire an event here that we can catch somewhere else that
            // needs to know when a post was created.
            event(new PostWasCreated($post));

            // Maybe we'll notify some users of the new post as well.
            dispatch(new PostNotifier($post));

            return true;
        }

        return false;
    }
}

Điều khiển :

namespace App\Http\Controllers;

use App\Post;
use App\Http\Requests\PostRequest;

class PostController extends Controller
{

   /**
    * Creates a new post.
    *
    * @return string
    */
    public function store(PostRequest $request)
    {
        if ($request->persist(new Post())) {
            flash()->success('Successfully created new post!');
        } else {
            flash()->error('There was an issue creating a post. Please try again.');
        }

        return redirect()->back();
    }

   /**
    * Updates a post.
    *
    * @return string
    */
    public function update(PostRequest $request, $id)
    {
        $post = Post::findOrFail($id);

        if ($request->persist($post)) {
            flash()->success('Successfully updated post!');
        } else {
            flash()->error('There was an issue updating this post. Please try again.');
        }

        return redirect()->back();
    }
}

Trong ví dụ trên, đầu vào yêu cầu được xác thực tự động và tất cả những gì chúng ta cần làm là gọi phương thức kiên trì và chuyển vào Bài đăng mới. Tôi nghĩ rằng khả năng đọc và bảo trì phải luôn luôn vượt trội các mẫu thiết kế phức tạp và không cần thiết.

Sau đó, bạn cũng có thể sử dụng phương pháp chính xác tương tự để cập nhật bài đăng, vì chúng tôi có thể kiểm tra xem bài đăng có tồn tại hay không và thực hiện logic xen kẽ khi cần.


nhưng - không phải công việc "được cho là" được xếp hàng? Đôi khi chúng ta có thể muốn nó được xếp hàng nhưng không phải lúc nào cũng vậy. Tại sao không sử dụng lệnh thay thế? Điều gì xảy ra nếu bạn muốn viết một số logic nghiệp vụ có thể được thực thi như một lệnh hoặc một sự kiện hoặc một hàng đợi?
Sabrina Leggett

1
Công việc không cần phải được xếp hàng. Bạn xác định rằng bằng cách triển khai giao diện trên công việc ShouldQueuemà Laravel cung cấp. Nếu bạn muốn viết Logic nghiệp vụ trong một lệnh hoặc sự kiện, chỉ cần kích hoạt công việc bên trong các sự kiện / lệnh đó. Công việc của Laravels cực kỳ linh hoạt, nhưng cuối cùng chúng chỉ là các lớp dịch vụ đơn giản.
Steve Bauman
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.