SF3在SF3文件夹结构中

Vla*_*ban 9 php domain-driven-design symfony

我正在考虑一个广告网站,用户可以登录,发布新的列表和搜索现有的列表.我将完全遵循DDD原则,这是我的第一个项目.我之前从未在Symfony做过任何DDD.

以下是我对此的看法.你能否告诉我这是否正确,并建议更好的方法?

我可以看到两个域:用户和列表

搜索/显示/发布功能将存在于清单域中.在用户域中登录/注销.

SF3目录的示例结构是

app/
   ListingBundle/
      src/
         Listing.php
         SearchService.php
         ListingRepositoryInterface.php
         Controller/
            public/
               ListingController.php
            protected/
               ListingController.php
         Resource/
           view/
              public/
                 detail.twig.html
              protected/
                 edit.twig.html

   UserBundle/
      src/
         User.php
         AuthService.php
         UserRepositoryInterface.php
         Controller/
            public/
               UserController.php
            protected/
               UserController.php
         Resource/
           view/
              public/
                 login.twig.html
              protected/
                 dashboard.twig.html

   PersistenceBundle
       src/
          UserRepository.php
          ListingRepository.php
Run Code Online (Sandbox Code Playgroud)

我的主要问题是:

  • 这个结构是否正确?
  • 拥有具有相同名称的单独的受保护和公共控制器是一个好主意吗?
  • 在网站的用户后端部分显示的内容显示用户发布的最新列表?这两个域之间的界限在哪里?
  • PersistenceBundle是一个好主意还是应该在User和Listing包中存在持久性?

Tho*_*och 18

框架和DDD

你在这里做了一个错误的假设,即"我将使用Symfony框架以DDD-ish方式实现我的应用程序".

不要这样做,框架只是一个实现细节,并为您的应用程序提供一种(更多)交付方法.我的意思是在六角形建筑的背景下应用.

如果从我们的某个上下文中查看以下示例,您会看到我们的ApiClient上下文包含三个层(顶级目录结构).应用程序(包含用例服务),(包含模型和行为)和基础结构(包含基础架构问题,如持久性和交付).我专注于Symfony集成和持久性,因为这是OP的原始问题:

src/ApiClient
??? Application
?   ??? ApiClient
?   ?   ??? CreateApiClient
?   ?   ??? DisableApiClient
?   ?   ??? EnableApiClient
?   ?   ??? GetApiClient
?   ?   ??? ListApiClient
?   ?   ??? RemoveApiClient
?   ?   ??? ChangeApiClientDetails
?   ??? ClientIpAddress
?   ?   ??? BlackListClientIpAddress
?   ?   ??? CreateClientIpAddress
?   ?   ??? ListByApiClientId
?   ?   ??? ListClientIpAddresses
?   ?   ??? WhiteListClientIpAddress
?   ??? InternalContactPerson
?       ??? CreateInternalContactPerson
?       ??? GetInternalContactPerson
?       ??? GetByApiClientId
?       ??? ListContacts
?       ??? ReassignApiClient
?       ??? Remove
??? Domain
?   ??? Model
?       ??? ApiClient
?       ??? ClientIpAddress
?       ??? InternalContactPerson
??? Infrastructure
    ??? Delivery
    ?   ??? Http
    ?       ??? SymfonyBundle
    ?           ??? Controller
    ?           ?   ??? ApiClientController.php
    ?           ?   ??? InternalContactController.php
    ?           ?   ??? IpAddressController.php
    ?           ??? DependencyInjection
    ?           ?   ??? Compiler
    ?           ?   ?   ??? EntityManagerPass.php
    ?           ?   ?   ??? RouterPass.php
    ?           ?   ??? Configuration.php
    ?           ?   ??? MetadataLoader
    ?           ?   ?   ??? Adapter
    ?           ?   ?   ?   ??? HateoasSerializerAdapter.php
    ?           ?   ?   ?   ??? JMSSerializerBuilderAdapter.php
    ?           ?   ?   ??? Exception
    ?           ?   ?   ?   ??? AmbiguousNamespacePathException.php
    ?           ?   ?   ?   ??? EmptyMetadataDirectoryException.php
    ?           ?   ?   ?   ??? FileException.php
    ?           ?   ?   ?   ??? MalformedNamespaceException.php
    ?           ?   ?   ?   ??? MetadataLoadException.php
    ?           ?   ?   ??? FileMetadataLoader.php
    ?           ?   ?   ??? MetadataAware.php
    ?           ?   ?   ??? MetadataLoaderInterface.php
    ?           ?   ??? MFBApiClientExtension.php
    ?           ??? DTO
    ?           ?   ??? ApiClient
    ?           ?       ??? ChangeInternalContact
    ?           ?           ??? ChangeInternalContactRequest.php
    ?           ?           ??? ChangeInternalContactResponse.php
    ?           ??? MFBApiClientBundle.php
    ?           ??? Resources
    ?           ?   ??? config
    ?           ?   ?   ??? domain_services.yml
    ?           ?   ?   ??? metadata_loader.yml
    ?           ?   ?   ??? routing.yml
    ?           ?   ?   ??? services.yml
    ?           ?   ??? hateoas
    ?           ?   ?   ??? ApiClient
    ?           ?   ?       ??? Application
    ?           ?   ?       ?   ??? ApiClient
    ?           ?   ?       ?   ?   ??? CreateApiClient
    ?           ?   ?       ?   ?   ?   ??? CreateApiClientResponse.yml
    ?           ?   ?       ?   ?   ??? ListApiClient
    ?           ?   ?       ?   ?       ??? ListApiClientResponse.yml
    ?           ?   ?       ?   ??? ClientIpAddress
    ?           ?   ?       ?   ?   ??? CreateClientIpAddress
    ?           ?   ?       ?   ?   ?   ??? CreateClientIpAddressResponse.yml
    ?           ?   ?       ?   ?   ??? ListByApiClientId
    ?           ?   ?       ?   ?   ?   ??? ListByApiClientIdResponse.yml
    ?           ?   ?       ?   ?   ??? ListClientIpAddresses
    ?           ?   ?       ?   ?       ??? ListClientIpAddressesResponse.yml
    ?           ?   ?       ?   ??? InternalContactPerson
    ?           ?   ?       ?       ??? Create
    ?           ?   ?       ?       ?   ??? CreateResponse.yml
    ?           ?   ?       ?       ??? List
    ?           ?   ?       ?           ??? ListResponse.yml
    ?           ?   ?       ??? Domain
    ?           ?   ?           ??? ApiClient
    ?           ?   ?           ?   ??? ApiClient.yml
    ?           ?   ?           ??? ClientIpAddress
    ?           ?   ?           ?   ??? ClientIpAddress.yml
    ?           ?   ?           ??? InternalContactPerson
    ?           ?   ?               ??? InternalContactPerson.yml
    ?           ?   ??? serializer
    ?           ?       ??? ApiClient
    ?           ?       ?   ??? Application
    ?           ?       ?   ?   ??? ApiClient
    ?           ?       ?   ?   ?   ??? CreateApiClient
    ?           ?       ?   ?   ?   ?   ??? ContactPersonRequest.yml
    ?           ?       ?   ?   ?   ?   ??? CreateApiClientRequest.yml
    ?           ?       ?   ?   ?   ?   ??? CreateApiClientResponse.yml
    ?           ?       ?   ?   ?   ??? GetApiClient
    ?           ?       ?   ?   ?       ??? GetApiClientResponse.yml
    ?           ?       ?   ?   ??? ClientIpAddress
    ?           ?       ?   ?   ?   ??? CreateClientIpAddress
    ?           ?       ?   ?   ?       ??? CreateClientIpAddressRequest.yml
    ?           ?       ?   ?   ?       ??? CreateClientIpAddressResponse.yml
    ?           ?       ?   ?   ??? InternalContactPerson
    ?           ?       ?   ?       ??? Create
    ?           ?       ?   ?       ?   ??? CreateRequest.yml
    ?           ?       ?   ?       ?   ??? CreateResponse.yml
    ?           ?       ?   ?       ??? Get
    ?           ?       ?   ?       ?   ??? GetResponse.yml
    ?           ?       ?   ?       ??? List
    ?           ?       ?   ?       ?   ??? ListResponse.yml
    ?           ?       ?   ?       ??? ReassignApiClient
    ?           ?       ?   ?           ??? ReassignApiClientRequest.yml
    ?           ?       ?   ??? Domain
    ?           ?       ?       ??? ApiClient
    ?           ?       ?       ?   ??? ApiClient.yml
    ?           ?       ?       ?   ??? ContactPerson.yml
    ?           ?       ?       ??? ClientIpAddress
    ?           ?       ?       ?   ??? ClientIpAddress.yml
    ?           ?       ?       ??? InternalContactPerson
    ?           ?       ?           ??? InternalContactPerson.yml
    ?           ?       ??? Bundle
    ?           ?           ??? DTO
    ?           ?               ??? ApiClient
    ?           ?                   ??? ChangeInternalContact
    ?           ?                       ??? ChangeInternalContactRequest.yml
    ?           ??? Service
    ?               ??? Hateoas
    ?                   ??? UrlGenerator.php
    ??? Persistence
        ??? Doctrine
        ?   ??? ApiClient
        ?   ?   ??? ApiClientRepository.php
        ?   ?   ??? mapping
        ?   ?       ??? ApiClientId.orm.yml
        ?   ?       ??? ApiClient.orm.yml
        ?   ?       ??? CompanyName.orm.yml
        ?   ?       ??? ContactEmail.orm.yml
        ?   ?       ??? ContactList.orm.yml
        ?   ?       ??? ContactName.orm.yml
        ?   ?       ??? ContactPerson.orm.yml
        ?   ?       ??? ContactPhone.orm.yml
        ?   ?       ??? ContractReference.orm.yml
        ?   ??? ClientIpAddress
        ?   ?   ??? ClientIpAddressRepository.php
        ?   ?   ??? mapping
        ?   ?       ??? ClientIpAddressId.orm.yml
        ?   ?       ??? ClientIpAddress.orm.yml
        ?   ?       ??? IpAddress.orm.yml
        ?   ??? InternalContactPerson
        ?       ??? InternalContactPersonRepository.php
        ?       ??? mapping
        ?           ??? InternalContactPersonId.orm.yml
        ?           ??? InternalContactPerson.orm.yml
        ??? InMemory
            ??? ApiClient
            ?   ??? ApiClientRepository.php
            ??? ClientIpAddress
            ?   ??? ClientIpAddressRepository.php
            ??? InternalContactPerson
                ??? InternalContactPersonRepository.php

94 directories, 145 files
Run Code Online (Sandbox Code Playgroud)

相当多的文件!

您可以看到我正在使用捆绑软件作为应用程序的端口(命名虽然有点,但它不应该是Http交付,因为严格意义上的六边形体系结构它是一个应用程序到应用程序端口) .我强烈建议你阅读PHP书中DDD,其中所有这些概念都是用PHP中的表达实例来解释的(假设你已经阅读了蓝皮书和红皮书,尽管这本书作为一个单独的工作,同时仍然提供参考).


Fab*_*ler 6

使用 Symfony 构建的 DDD 应用程序的文件夹结构

我支持 tPl0ch 的回答,但我想提出一个文件夹结构的轻微变体,这在我参与的 Symfony 的几个项目中很有用。 对于您的特定域,文件夹结构可能如下所示:

app
    Listing
        Domain
            Model
                Listing.php
            Repository
                ListingRepository.php
            Service
                SearchService.php
        Infrastructure
            Repository
                DoctrineListingRepository.php   // or some other implementation
            Resources
                // symfony & doctrine config etc.
            Service
                ElasticSearchService.php        // or some other implementation
            ListingInfrastructureBundle.php
        Presentation
            Controller
                ViewListingController.php       // assuming this is the "public" part
                EditListingController.php       // assuming this is the "protected" part
            Forms
                ListingForm.php
            Resources
                // symfony config & views etc.
            ListingPresentationBundle.php
    User
        // ...
        Infrastructure
            Service
                AuthService.php
        // ...
Run Code Online (Sandbox Code Playgroud)

使用此文件夹结构,您可以将洋葱架构的不同层分开。不同的文件夹清楚地传达了层之间的边界和允许的依赖关系。我写了一篇关于使用 Symfony 的 DDD 文件夹结构的博客文章,其中详细描述了该方法。


其他资源:

除此之外,我还建议您查看以下资源:

  • PHP DDD Cargo Sample : Eric Evans DDD 书中使用的货物示例的 PHP 7 版本
  • Sylius:电子商务 PHP 框架构建在 Symfony 之上,具有基于组件的架构

我从理解 Sylius 代码库中学到了很多东西——这是一个真实世界的项目,而且相当庞大。他们进行了各种测试,并为交付高质量的代码付出了很多努力。