Helpex - Trao đổi & giúp đỡ Đăng nhập

Triển khai thiết kế hướng tên miền trong PHP

Domain-Driven Design là một phương pháp phát triển phần mềm để giải quyết các dự án phần mềm phức tạp để cung cấp một sản phẩm cuối đáp ứng các mục tiêu của tổ chức. Trên thực tế, Domain-Driven Design thúc đẩy tập trung dự án vào một mô hình cốt lõi đang phát triển.

Nó sẽ dạy cho bạn cách mô hình hóa thế giới thực trong ứng dụng của bạn một cách hiệu quả và sử dụng OOP để gói gọn logic kinh doanh của tổ chức.

Mô hình miền là gì?

Theo tôi, Mô hình miền là nhận thức của bạn về bối cảnh mà nó áp dụng. Hãy để tôi mô tả nó một chút nữa. 'Tên miền' có nghĩa là thế giới của doanh nghiệp bạn đang làm việc và các vấn đề họ muốn giải quyết. Ví dụ: nếu bạn muốn phát triển một ứng dụng phân phối thực phẩm trực tuyến, tên miền của bạn sẽ là tất cả mọi thứ (vấn đề, quy tắc kinh doanh, v.v.) về việc phân phối thực phẩm trực tuyến cần được thực hiện trong dự án của bạn.

Mô hình miền là giải pháp có cấu trúc của bạn cho vấn đề. Mô hình miền cần thể hiện các từ vựng và khái niệm chính về các vấn đề của miền.

Ngôn ngữ phổ biến:

'Ngôn ngữ phổ biến' là ngôn ngữ được các chuyên gia kinh doanh sử dụng để mô tả Mô hình miền. Điều đó có nghĩa là nhóm phát triển sử dụng ngôn ngữ một cách nhất quán trong tất cả các giao tiếp và cả trong mã. Ngôn ngữ này nên dựa trên Mô hình miền. Để tôi lấy một ví dụ:

    $product = new Entity / Product();
    $product - > setTitle(new Title('Mobile Phone'));
    $product - > setPrice(new Price('1000'));
    $this - > em - > persist($product);
    $this - > em - > flush();

Trong đoạn mã trên, tôi tạo một sản phẩm mới, nhưng trong ứng dụng, sản phẩm phải được thêm vào, không được tạo:

    //add is a static method in product class
    $product = Product::add(
        new Title('Mobile Phone'),
        new Price('1000')
    );

Trong một nhóm phát triển, nếu ai đó tạo ra một sản phẩm và ai đó thêm một sản phẩm, điều này sẽ vi phạm ngôn ngữ phổ biến. Trong trường hợp này, nếu trong phương thức thêm sản phẩm, chúng tôi có một số hành động bổ sung như gửi email, tất cả chúng sẽ bị bỏ qua và định nghĩa thêm sản phẩm trong nhóm sẽ thay đổi. Chúng tôi sẽ có hai định nghĩa khác nhau cho một thuật ngữ.

Kiến trúc lớp:

Trong bài viết này, tôi không có kế hoạch nói về thiết kế hướng đối tượng. Nhưng Thiết kế hướng tên miền đề xuất các nguyên tắc cơ bản của một thiết kế tốt. Eric Evans tin rằng:

Phát triển một mô hình miền tốt là một nghệ thuật.

Để phát triển một mô hình miền tốt, bạn cần biết về Thiết kế theo mô hình. Sự kết nối của mô hình và việc triển khai được gọi là Thiết kế hướng mô hình. Kiến trúc lớp là một trong những khối Thiết kế theo mô hình.

Kiến trúc lớp là ý tưởng của sự cô lập của từng phần dựa trên nhiều năm kinh nghiệm và quy ước. Các lớp được liệt kê dưới đây:

  • Giao diện người dùng
  • Lớp ứng dụng
  • Lớp miền
  • Lớp cơ sở hạ tầng

Các giao diện người dùng có trách nhiệm hiển thị thông tin cho người sử dụng và giải thích các lệnh của người dùng. Trong Laravel, chế độ xem là Lớp Giao diện người dùng (bản trình bày). Lớp ứng dụng là cách chúng ta giao tiếp với thế giới bên ngoài (ngoài miền ứng dụng). Lớp này hoạt động như một API công khai cho ứng dụng của chúng tôi. Nó không chứa các quy tắc kinh doanh hoặc kiến ​​thức. Bộ điều khiển ở Laravel được đặt ở đây.

Lớp tên miền là trái tim của phần mềm kinh doanh. Lớp này chịu trách nhiệm đại diện cho các khái niệm về doanh nghiệp, thông tin về tình hình kinh doanh và quy tắc kinh doanh. Tầng cơ sở cung cấp các khả năng kỹ thuật chung hỗ trợ các lớp cao hơn và cũng hỗ trợ mô hình tương tác giữa bốn lớp (đó là lý do tại sao các kho lưu trữ được đặt trong lớp này).

Sự kết nối giữa các lớp là bắt buộc, nhưng không làm mất lợi ích của việc phân tách. Kết nối sẽ theo một hướng. Như bạn thấy trong lược đồ trên, các lớp trên có thể giao tiếp với các lớp thấp hơn. Nếu các lớp thấp hơn cần kết nối với một lớp trên, chúng phải sử dụng các mẫu như gọi lại hoặc quan sát.

Đối tượng và thực thể giá trị:

Tôi là một fan hâm mộ lớn của các Đối tượng Giá trị. Tôi nghĩ họ là trái tim của OOP. Mặc dù chúng có vẻ đơn giản, nhưng các đối tượng giá trị DDD là một điểm gây nhầm lẫn nghiêm trọng cho nhiều người, bao gồm cả tôi. Tôi đã đọc và nghe rất nhiều cách khác nhau để mô tả các đối tượng giá trị từ nhiều khía cạnh khác nhau. May mắn thay, mỗi cách giải thích khác nhau, thay vì mâu thuẫn với nhau, đã giúp tôi xây dựng sự hiểu biết sâu sắc hơn về các đối tượng giá trị.

Các đối tượng giá trị có thể truy cập bằng giá trị của chúng chứ không phải danh tính. Họ là những đối tượng bất di bất dịch. Giá trị của chúng không thay đổi (hoặc hiếm khi thay đổi) và không có vòng đời (có nghĩa là chúng không giống như một hàng trong bảng cơ sở dữ liệu của bạn có thể bị xóa), chẳng hạn như tiền tệ, ngày, quốc gia, v.v.

Bạn có thể tạo các đối tượng giá trị mà bạn không nhận ra là đối tượng giá trị. Ví dụ: địa chỉ email có thể là một chuỗi hoặc nó có thể là một đối tượng giá trị với tập hợp các hành vi của chính nó.

Mã dưới đây là một lớp đối tượng giá trị mẫu:

//...
final class ImagesTypeValueObject {
    private $imageType;
    private $validImageType = ['JPEG', 'GIF', 'BMP', 'TIFF', 'PNG'];

    public
    function __construct($imageType) {
        Assertion::inArray($this - > validImageType, $imageType, 'Sorry The entry is wrong please entre valid image type');
        $this - > imageType = $imageType;
    }

    public
    function __toString() {
        return $this - > imageType;
    }
}

Các thực thể là các đối tượng có thể truy cập bằng một danh tính trong ứng dụng của chúng tôi. Chính xác, trên thực tế, một thực thể là một tập hợp các thuộc tính có một định danh duy nhất. Một hàng các bảng cơ sở dữ liệu sẽ là một ví dụ tốt. Một thực thể có thể thay đổi, bởi vì nó có thể thay đổi các thuộc tính của nó (thường là với setters và getters) và nó cũng có vòng đời, có nghĩa là nó có thể bị xóa.

Có một đối tượng đại diện cho một cái gì đó với tính liên tục và bản sắc - một cái gì đó được theo dõi thông qua các trạng thái khác nhau hoặc thậm chí qua các triển khai khác nhau? Hay đó là một thuộc tính mô tả trạng thái của một cái gì đó khác? Đây là điểm khác biệt cơ bản giữa Thực thểĐối tượng Giá trị .

Cốt liệu:

Một mô hình có thể chứa một số lượng lớn các đối tượng miền. Cho dù chúng tôi đã cân nhắc bao nhiêu vào việc mô hình hóa một miền, điều thường xảy ra là nhiều đối tượng phụ thuộc vào nhau, tạo ra một tập hợp các mối quan hệ và bạn không thể chắc chắn 100% về kết quả. Nói cách khác, bạn nên lưu ý đến quy tắc kinh doanh phải luôn nhất quán trong mô hình miền của bạn; Chỉ với kiến ​​thức đó, bạn có thể tự tin về mã của mình.

Các uẩn giúp giảm số lượng liên kết hai chiều giữa các đối tượng trong hệ thống vì bạn chỉ được phép lưu trữ các tham chiếu đến thư mục gốc. Điều đó đơn giản hóa đáng kể thiết kế và giảm số lượng thay đổi mù trong biểu đồ đối tượng. Mặt khác, tập hợp giúp tách rời các cấu trúc lớn bằng cách đặt quy tắc cho các mối quan hệ giữa các thực thể. (Lưu ý: Tập hợp cũng có thể có các thuộc tính, phương thức và bất biến không phù hợp trong một lớp duy nhất)

Để triển khai tổng hợp trong các ứng dụng của chúng tôi, Eric Evans đã đặt ra một số quy tắc trong cuốn sách của mình và tôi liệt kê chúng dưới đây:

  • Các thực thể gốc có một bản sắc toàn cầu và cuối cùng chịu trách nhiệm kiểm tra các bất biến.
  • Các thực thể gốc có một bản sắc toàn cầu. Các thực thể bên trong ranh giới có một bản sắc địa phương, chỉ duy nhất trong tổng hợp.
  • Không có gì bên ngoài ranh giới tổng hợp có thể giữ một tham chiếu đến bất cứ thứ gì bên trong, ngoại trừ thực thể gốc. Thực thể gốc có thể trao tham chiếu đến các thực thể bên trong cho các đối tượng khác, nhưng các đối tượng đó chỉ có thể sử dụng chúng tạm thời và không thể giữ tham chiếu.
  • Như một hệ quả của quy tắc trên, chỉ có thể lấy được các gốc tổng hợp trực tiếp với các truy vấn cơ sở dữ liệu. Tất cả các đối tượng khác phải được tìm thấy bởi các hiệp hội.
  • Các đối tượng trong tập hợp có thể giữ các tham chiếu đến các gốc tổng hợp khác.
  • Một thao tác xóa phải xóa tất cả mọi thứ trong ranh giới tổng hợp cùng một lúc (với bộ sưu tập rác, việc này rất dễ dàng. Vì không có tài liệu tham khảo bên ngoài cho bất cứ thứ gì ngoài gốc, hãy xóa gốc và mọi thứ khác sẽ được thu thập).
  • Khi một thay đổi đối với bất kỳ đối tượng nào trong ranh giới tổng hợp được cam kết, tất cả các bất biến của toàn bộ tổng hợp phải được thỏa mãn.

Các nhà máy:

Trong thế giới OOP, một Nhà máy đề cập đến một đối tượng có trách nhiệm duy nhất là tạo ra các đối tượng khác. Trong Thiết kế hướng tên miền, các nhà máy được sử dụng để gói gọn kiến ​​thức cần thiết cho việc tạo đối tượng và chúng đặc biệt hữu ích để tạo Tập hợp.

Một gốc tổng hợp cung cấp Phương thức xuất xưởng để tạo các thể hiện của loại Tổng hợp khác (hoặc các phần bên trong) sẽ có trách nhiệm chính là cung cấp hành vi Tổng hợp chính của nó, Phương thức xuất xưởng chỉ là một trong số đó. Các nhà máy cũng có thể cung cấp một lớp trừu tượng quan trọng giúp bảo vệ khách hàng khỏi bị phụ thuộc vào một lớp cụ thể cụ thể.

Có những lúc Nhà máy không cần thiết, và một nhà xây dựng đơn giản là đủ. Sử dụng một hàm tạo khi:

  • Việc xây dựng không phức tạp.
  • Việc tạo ra một đối tượng không liên quan đến việc tạo ra các đối tượng khác và tất cả các thuộc tính cần thiết được truyền qua hàm tạo.
  • Nhà phát triển quan tâm đến việc thực hiện và có lẽ muốn chọn chiến lược được sử dụng.
  • Lớp học là loại. Không có hệ thống phân cấp liên quan, vì vậy không cần phải chọn giữa một danh sách các triển khai cụ thể.

Kho lưu trữ:

Kho lưu trữ về cơ bản là một lớp nằm giữa miền của dự án và cơ sở dữ liệu. Martin Fowler, trong cuốn sách  Các mô hình kiến ​​trúc ứng dụng doanh nghiệp , đã viết rằng một kho lưu trữ

Trung gian giữa các lớp ánh xạ dữ liệu và miền bằng cách sử dụng giao diện giống như bộ sưu tập để truy cập các đối tượng miền.

Điều này có nghĩa là bạn nên nghĩ đến việc truy cập dữ liệu trong cơ sở dữ liệu của mình giống như cách bạn sẽ làm việc với một đối tượng thu thập tiêu chuẩn.

Hãy để tôi giải thích thêm một chút. Hãy tưởng tượng trong Thiết kế hướng tên miền, bạn có thể cần phải tạo một đối tượng, với một nhà xây dựng hoặc một nhà máy; bạn phải yêu cầu nó từ thư mục gốc của Uẩn. Vấn đề bây giờ là nhà phát triển phải có một tham chiếu đến root. Đối với các ứng dụng lớn, điều này trở thành một vấn đề bởi vì người ta phải đảm bảo rằng các nhà phát triển luôn có một tham chiếu đến đối tượng cần thiết. Điều này sẽ dẫn đến các nhà phát triển tạo ra một loạt các hiệp hội không thực sự cần thiết.

Một lý do khác tại sao các kho lưu trữ là vấn đề truy cập cơ sở dữ liệu. Lập trình viên không được biết các chi tiết cần thiết để truy cập cơ sở dữ liệu. Vì cơ sở dữ liệu nằm trong lớp cơ sở hạ tầng, nó phải xử lý nhiều chi tiết cơ sở hạ tầng thay vì xử lý các khái niệm miền. Hơn nữa, nếu nhà phát triển yêu cầu một truy vấn để chạy, điều này sẽ dẫn đến việc tiết lộ nhiều hơn các chi tiết nội bộ của truy vấn cần thiết.

Nếu chúng ta không có kho lưu trữ, tiêu điểm tên miền sẽ bị mất và thiết kế sẽ bị xâm phạm. Vì vậy, nếu nhà phát triển sử dụng truy vấn để truy cập dữ liệu từ cơ sở dữ liệu hoặc kéo một vài đối tượng cụ thể, logic miền sẽ chuyển sang truy vấn và mã nhà phát triển, do đó, các tổng hợp sẽ vô dụng.

Cuối cùng, kho lưu trữ hoạt động như một nơi lưu trữ cho các đối tượng có thể truy cập toàn cầu. Các kho lưu trữ cũng có thể bao gồm một chiến lược. Nó có thể truy cập vào một bộ lưu trữ bền vững hoặc một bộ lưu trữ khác dựa trên chiến lược đã chỉ định.

Triển khai tại Laravel:

Như bạn có thể đã biết, lựa chọn tốt nhất để triển khai DDD trong PHP là ORM của Học thuyết. Để triển khai tổng hợp và kho lưu trữ, chúng tôi cần thực hiện một số thay đổi trong các thực thể của chúng tôi và tạo một số tệp trong lớp miền của chúng tôi.

Hôm nay tôi đã quyết định triển khai một phần nhỏ của ứng dụng mà người dùng có thể tạo một trang hoặc sửa đổi nó. Mỗi trang có thể chứa nhiều bình luận và mỗi bình luận có thể có một số bình luận phụ. Quản trị viên có thể phê duyệt / từ chối bình luận sau khi chúng được thêm vào.

Trong kịch bản trên, bước đầu tiên là tạo một kho lưu trữ cơ sở trong lớp miền của bạn, một kho lưu trữ cơ sở có nguồn gốc từ Doctrine EntityRep repository, sẽ cho phép chúng ta có tất cả các chức năng Kho lưu trữ tài liệu tích hợp. Chúng tôi cũng có thể đặt chức năng chung của chúng tôi ở đây và tất cả các kho lưu trữ của chúng tôi phải kế thừa từ nó. Việc thực hiện trông như thế này:

namespace App\ Domain\ Repositories\ Database\ DoctrineORM;

use App\ Domain\ Events\ Doctrine\ DoctrineEventSubscriber;
use Doctrine\ Common\ Persistence\ Event\ LifecycleEventArgs;
use Doctrine\ ORM\ EntityRepository;
use Doctrine\ ORM\ Mapping\ ClassMetadata;
use Doctrine\ ORM\ EntityManager;
use GeneratedHydrator\ Configuration;
use Doctrine\ Common\ Collections\ ArrayCollection;

abstract class DoctrineBaseRepository extends EntityRepository {
    public $primaryKeyName;
    public $entityName = null;

    public
    function __construct(EntityManager $em) {
        parent::__construct($em, new ClassMetadata($this - > entityClass));
        $this - > primaryKeyName = $em - > getClassMetadata($this - > entityClass) - > getSingleIdentifierFieldName();
    }

}


Chúng tôi có hai kho lưu trữ. Cái đầu tiên là kho lưu trữ trang và cái thứ hai là kho lưu trữ bình luận. Tất cả các kho lưu trữ phải có thuộc entityClasstính để xác định một lớp thực thể. Trong trường hợp này, chúng tôi có thể đóng gói (tài sản riêng) thực thể vào kho của chúng tôi:


namespace App\ Domain\ Repositories\ Database\ DoctrineORM\ Page;

use App\ Domain\ User\ Core\ Model\ Entities\ Pages;
use App\ Domain\ Repositories\ Database\ DoctrineORM\ DoctrineBaseRepository;

class DoctrinePageRepository extends DoctrineBaseRepository {
    private $entityClass = Pages::class;
    //...
    public
    function AddComments($pages) {
        $this - > _em - > merge($pages);
        $this - > _em - > flush();
    }

}


Tôi sử dụng dòng lệnh Doctrine để tạo các thực thể của mình:


namespace App\ Domain\ Interactions\ Core\ Model\ Entities;

use App\ Domain\ User\ Comments\ Model\ Entities\ Comments;
use Doctrine\ Common\ Collections\ ArrayCollection;
use Doctrine\ ORM\ Mapping as ORM;

/**
 * Pages
 *
 * @ORM\Table(name="pages")
 * @ORM\Entity
 */
class Pages {
    /**
     * @var string
     *
     * @ORM\Column(name="page_title", type="string", length=150, nullable=false)
     */
    private $pageTitle;

    /**
     * @ORM\OneToMany(targetEntity="App\Domain\User\Comments\Model\Entities\Comments", mappedBy="pageId", indexBy="pageId", cascade={"persist", "remove"})
     */
    private $pageComment;

    /**
     * @var integer
     *
     * @ORM\Column(name="page_id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $pageId;

    //.. unnecessary properties are omitted here !

    public
    function __construct() {

        $this - > pageComment = new ArrayCollection();
    }


    /**
     * @param Comment
     *
     * @return void
     */
    public
    function addComments(Comments $comment) {
            $this - > pageComment[] = $comment;
        }
        //... other setters and getters.
}



namespace App\ Domain\ User\ Comments\ Model\ Entities;
use Doctrine\ ORM\ Mapping as ORM;

/**
 * Comments
 *
 * @ORM\Table(name="comments")
 * @ORM\Entity
 */
class Comments {
    /**
     * @ORM\ManyToOne(targetEntity="App\Domain\User\Core\Model\Entities\Users")
     * @ORM\JoinColumn(name="users_user_id", referencedColumnName="id")
     */
    private $usersUserId;
    //...

    /**
     * @ORM\ManyToOne(targetEntity="comments", inversedBy="children")
     * @ORM\JoinColumn(name="parent_id", referencedColumnName="comment_id")
     */
    private $parentId;


    /**
     * @ORM\ManyToOne(targetEntity="App\Domain\Interactions\Core\Model\Entities\pages", inversedBy="pageComment" )
     * @ORM\JoinColumn(name="page_id", referencedColumnName="page_id")
     */
    private $pageId;

    /**
     * @ORM\OneToMany(targetEntity="comments", mappedBy="parent")
     */
    private $children;

    //...
    /**
     * @param Page
     *
     * @return void
     */
    public
    function __construct() {
            $this - > children = new\ Doctrine\ Common\ Collections\ ArrayCollection();
        }
        //...

}


Như bạn có thể thấy, trong đoạn mã trên tôi xác định các mối quan hệ trong các chú thích thực thể. Việc thực hiện các mối quan hệ trong Học thuyết ORM có vẻ rất phức tạp, nhưng thực sự không khó lắm khi bạn làm quen với cách mọi thứ hoạt động. Cách duy nhất bạn có thể thêm nhận xét là bằng cách gọi addCommentstrong pagethực thể và phương thức đó chỉ chấp nhận một commentđối tượng thực thể làm đầu vào. Điều này sẽ làm cho chúng tôi chắc chắn về chức năng mã của chúng tôi.

Tổng hợp của tôi trông như:

namespace App\ Domain\ Comment;
use App\ Domain\ User\ Comments\ Model\ Entities\ Comments;
use App\ Domain\ Repositories\ Database\ DoctrineORM\ User\ DoctrineCommentRepository;
use App\ Domain\ Repositories\ Database\ DoctrineORM\ Interactions\ DoctrinePagesRepository;
use Assert\ Assertion;

class PageAggregate {

    public $Pages;
    public $pageResult;
    public $parentId = null;
    public $comments;
    public $DoctrineRepository = DoctrinePagesRepository::class;

    public
    function __construct($id, $comments = null, $administrative = null) {
        $this - > DoctrineRepository = \App::make($this - > DoctrineRepository);
        Assertion::notNull($this - > pageResult = $this - > DoctrineRepository - > findOneBy(['pageId' => $id]), 'sorry the valid page id is required here');
        $commentFacory = new Commentfactory($this - > pageResult, $comments);
        return $commentFacory - > choisir($administrative);
    }
}


Chúng tôi cần một tổng hợp chịu trách nhiệm giới hạn quyền truy cập vào các bình luận chỉ khi nó hợp lệ PageId; Tôi có nghĩa là không có PageId, truy cập commentslà không thể. Hãy nói rằng commentskhông có giá trị page idkhông có ý nghĩa và không thể truy cập. Ngoài ra, có một commentphương pháp nhà máy giúp chúng tôi gói gọn các quy tắc kinh doanh.

And the factory method:

namespace App\ Domain\ Comment;

interface CommentTypeFactoryInterface {
    public
    function confectionner();

}



namespace App\ Domain\ Comment;

interface CommentFactoryInterface {
    public
    function choisir();
}


I defined two factories. The first one is the type of comments and the second one is the comment interfaces which make it mandatory for every comment to implement choisir method.


namespace App\ Domain\ Comment;
use App\ Application\ Factory\ Request\ RequestFactory;

class Commentfactory implements CommentFactoryInterface {
    private $page;
    private $comment;
    private $parentId;

    public
    function __construct($page, $comment = null) {
        $this - > page = $page;
        $this - > comment = $comment;
    }

    public
    function choisir($administrative = null) {
        // TODO: Implement choisir() method.
        if (is_null($administrative)) {
            $comment = new Comment($this - > page, $this - > comment);
            return $comment - > confectionner();
        }

        $comment = new AdministrativeComments($this - > page, $this - > comment, $this - > parentId);
        return $comment - > confectionner();
    }


}


The Comment Factory method provides inner parts of the aggregate.


namespace App\ Domain\ Comment;

use App\ Domain\ User\ Comments\ Model\ Entities\ Comments;
use App\ Domain\ Repositories\ Database\ DoctrineORM\ User\ DoctrineCommentRepository;
use App\ Domain\ Repositories\ Database\ DoctrineORM\ Interactions\ DoctrinePagesRepository;
use App\ Domain\ Interactions\ Core\ Model\ Entities\ Pages;
use App\ Application\ Factory\ Request\ RequestFactory;
use Assert\ Assertion;

class Comment implements CommentTypeFactoryInterface {
    private $page;
    private $comments;
    public $DoctrineCommentRepository = DoctrineCommentRepository::class;
    public $DoctrineRepository = DoctrinePagesRepository::class;

    public
    function __construct(Pages $page, $comment) {
        $this - > page = $page;
        $this - > comments = $comment;
        $this - > DoctrineCommentRepository = \App::make($this - > DoctrineCommentRepository);
        $this - > DoctrineRepository = \App::make($this - > DoctrineRepository);

    }

    public
    function confectionner() {
        if (is_array($this - > comments)) {\
            Request::replace($this - > comments['data']);\
            App::make(RequestFactory::class);

            $this - > addComments();
        }
        elseif(is_null($this - > comments)) {
            return $this - > retrieveComments();
        }
        elseif(is_int($this - > comments)) {
            $this - > deleteComment();
        }
        return true;

    }

    private
    function addComments() {
        if (isset($this - > comments['id']) && !is_null($this - > comments['object'] = $this - > DoctrineCommentRepository - > findOneBy(['commentId' => $this - > comments['id']])))
            return $this - > editComment();

        $this - > comments = $this - > CommentObjectMapper(new Comments(), $this - > comments['data']);
        $this - > page - > addComments($this - > comments);
        $this - > DoctrineRepository - > AddComments($this - > page);
    }

    private
    function editComment() {
        $comment = $this - > CommentObjectMapper($this - > comments['object'], $this - > comments['data']);
        $this - > page - > addComments($comment);
        $this - > DoctrineRepository - > AddComments($this - > page);
    }

    private
    function deleteComment() {
        $this - > DoctrineCommentRepository - > delComments($this - > comments);
    }

    private
    function retrieveComments() {
        return $this - > page - > getPageComment();
    }

    //...

}



namespace App\ Domain\ Comment;

use App\ Domain\ Interactions\ Core\ Model\ Entities\ Pages;
use App\ Domain\ Repositories\ Database\ DoctrineORM\ User\ DoctrineCommentRepository;
use App\ Domain\ Repositories\ Database\ DoctrineORM\ Interactions\ DoctrinePagesRepository;
use App\ Domain\ User\ Comments;
use Assert\ Assertion;

class AdministrativeComments implements CommentTypeFactoryInterface {

    private $page;
    private $comments;
    private $parentId;
    private $privilege;
    public $DoctrineCommentRepository = DoctrineCommentRepository::class;
    public $DoctrineRepository = DoctrinePagesRepository::class;

    public
    function __construct(Pages $page, $comment, $parentId) {
        $this - > page = $page;
        $this - > comments = $comment;
        $this - > parentId = $parentId;
        $this - > privilege = new Athurization(\Auth::gaurd('admin') - > user());

    }

    public
    function confectionner() {
        $action = $this - > comments['action'];
        Assertion::notNull($this - > comments = $this - > DoctrineCommentRepository - > findOneBy(['commentId' => $this - > comments['id']]), 'no Valid comment Id');
        $this - > $action;
        return true;
    }

    public
    function approve() {
        $this - > privilege - > isAuthorize(__METHOD__);
        $this - > DoctrineCommentRepository - > approve($this - > comments, \Auth::gaurd('admin') - > user());
    }

    public
    function reject() {
        $this - > privilege - > isAuthorize(__METHOD__);
        $this - > DoctrineCommentRepository - > reject($this - > comments, \Auth::gaurd('admin') - > user());
    }

    public
    function delete() {
        $this - > privilege - > isAuthorize(__METHOD__);
        $this - > DoctrineCommentRepository - > delete($this - > comments, \Auth::gaurd('admin') - > user());
    }

    //...
}


As you see in the code above we have two class Comment and AdministrativeComments. The Commentfactory will decide which class must use. Some unnecessary class or methods such as Authorization class and reject method are omitted here. As you might see in the code above, I use RequestFactory for validation. This is the other factory method in our application that is responsible for validating input data. This kind of validation has a definition in Domain-Driven Design and also added in laravel 5+.

Conclusion:

Covering all of these definitions would require many articles, but I have done my best to summarize it. That was only a simple example of an aggregate root, but you can create your own sophisticated aggregate, and I hope this example helped.

1 hữu ích 0 bình luận 8.8k xem chia sẻ

Có thể bạn quan tâm

loading