├── .gitignore ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── composer.json └── src └── Black └── DDD └── DDDinPHP ├── Application ├── DTO │ ├── Assembler.php │ └── DTO.php ├── Service │ └── ApplicationService.php └── Specification │ └── Specification.php ├── Domain ├── Event │ └── DomainEvent.php └── Model │ ├── Entity.php │ ├── Repository.php │ └── ValueObject.php └── Infrastructure └── Service └── InfrastructureService.php /.gitignore: -------------------------------------------------------------------------------- 1 | composer.lock 2 | composer.phar 3 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Contributing 2 | ============ 3 | 4 | First of all, **thank you** for contributing, **you are awesome**! 5 | 6 | Here are a few rules to follow in order to ease code reviews, and discussions before 7 | maintainers accept and merge your work. 8 | 9 | You MUST follow the [PSR-1](http://www.php-fig.org/psr/1/) and 10 | [PSR-2](http://www.php-fig.org/psr/2/). If you don't know about any of them, you 11 | should really read the recommendations. Can't wait? Use the [PHP-CS-Fixer 12 | tool](http://cs.sensiolabs.org/). 13 | 14 | You MUST run the test suite. 15 | 16 | You MUST write (or update) unit tests. 17 | 18 | You SHOULD write documentation. 19 | 20 | Please, write [commit messages that make 21 | sense](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html), 22 | and [rebase your branch](http://git-scm.com/book/en/Git-Branching-Rebasing) 23 | before submitting your Pull Request. 24 | 25 | One may ask you to [squash your 26 | commits](http://gitready.com/advanced/2009/02/10/squashing-commits-with-rebase.html) 27 | too. This is used to "clean" your Pull Request before merging it (we don't want 28 | commits such as `fix tests`, `fix 2`, `fix 3`, etc.). 29 | 30 | Also, while creating your Pull Request on GitHub, you MUST write a description 31 | which gives the context and/or explains why you are creating it. 32 | 33 | Thank you! -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 La Blackroom 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | DDD PHP 2 | ======= 3 | 4 | __DDD in PHP__ is a simple project (a folder structure) for your project build with [Domain Driven Design](http://dddcommunity.org/). 5 | 6 | [![Latest Stable Version](https://poser.pugx.org/black/ddd-php/v/stable.png)](https://packagist.org/packages/black/ddd-php) 7 | [![Total Downloads](https://poser.pugx.org/black/ddd-php/downloads.png)](https://packagist.org/packages/black/ddd-php) 8 | 9 | Installation 10 | ------------ 11 | 12 | The recomanded way to install DDD in PHP is through [Composer](http://getcomposer.org/): 13 | 14 | ```json 15 | { 16 | "require": { 17 | "black/ddd-php": "@stable" 18 | } 19 | } 20 | ``` 21 | 22 | __Protip:__ You should browse the [`black/ddd-php`](https://packagist.org/packages/black/ddd-php) page to choose a stable version to use, avoid the `@stable` meta 23 | constraint. 24 | 25 | Why? 26 | ---- 27 | 28 | First, I want to create a folder structure for my continuous project based on semantic. This small library is a good 29 | start for my project and, even if some parts of this integration versus DDD rules are questionable, this library will 30 | work for a lot of projects. 31 | 32 | Usage 33 | ----- 34 | 35 | This project is a simple folder structure with interfaces (with simple contracts). Follow this structure and your project 36 | will follow DDD (not exactly true but your design will be fine). 37 | 38 | Why you should not use this library in your project? 39 | --- 40 | 41 | For a lot of good reasons like : 42 | 43 | - Repository interface is in Domain\Model with 4 basics functions. If you want to add CQRS pattern over this interface, you 44 | will need a Read and a Write side so you can't scale with this interface. 45 | 46 | - Repository::find() need a ValueObject. Create a concrete ValueObject implementing ValueObjectInterface and job is done... Or not 47 | You can't accept all ValueObject for find so you will write a condition for testing the $id and use or throw an InvalidArgumentException. 48 | 49 | So my advice (after 17 months) is: Do you want to create a DDD project? If yes, follow the rules of this package and you will create a DDD 50 | project but you should not implement this in your project. 51 | 52 | Contributing 53 | ------------ 54 | 55 | This project is a work in progress so don't hesitate to see CONTRIBUTING file and submit your PR. 56 | 57 | Credits 58 | ------- 59 | 60 | This README is heavily inspired by [Hateoas](https://github.com/willdurand/Hateoas) library by the great [@willdurand](https://github.com/willdurand). 61 | This guy needs your [PR](http://williamdurand.fr/2014/07/02/resting-with-symfony-sos/) for the sake of the REST in PHP. 62 | 63 | Alexandre "pocky" Balmes [alexandre@lablackroom.com](mailto:alexandre@lablackroom.com). 64 | Send me [Flattrs](https://flattr.com/profile/alexandre.balmes) if you love my work, [buy me gift](http://www.amazon.fr/registry/wishlist/3OR3EENRA5TSK) or hire me! 65 | 66 | 67 | License 68 | ------- 69 | `DDD in PHP` is released under the MIT License. See the bundled LICENSE file for details. 70 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "black/ddd-php", 3 | "type": "library", 4 | "description": "Implements DDD in PHP", 5 | "keywords": ["library", "black-project", "ddd"], 6 | "homepage": "http://www.lablackroom.com", 7 | "license": "MIT", 8 | "authors": [ 9 | { 10 | "name": "Alexandre 'pocky' Balmes ", 11 | "email": "alexandre@lablackroom.com", 12 | "homepage": "http://www.lablackroom.com" 13 | } 14 | ], 15 | "autoload": { 16 | "psr-4": { 17 | "Black\\DDD\\DDDinPHP\\": "src/Black/DDD/DDDinPHP/" 18 | } 19 | }, 20 | "require": { 21 | "php": ">=5.4.0" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Black/DDD/DDDinPHP/Application/DTO/Assembler.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Black\DDD\DDDinPHP\Application\DTO; 13 | 14 | use Black\DDD\DDDinPHP\Domain\Model\Entity; 15 | 16 | /** 17 | * Interface Assembler 18 | * 19 | * A DTO assembler is a special service to transform/reverse transform an Entity to a Data Transfer Object. 20 | * Use this (optional) and not pure-DDD service if you want to centralize the transformation of your Data Transfer 21 | * Object. 22 | */ 23 | interface Assembler 24 | { 25 | /** 26 | * Transform an Entity to a Data Transfer Object 27 | * 28 | * @param Entity $entity 29 | * @return mixed 30 | */ 31 | public function transform(Entity $entity); 32 | 33 | /** 34 | * Transform a Data Transfer Object to an Entity 35 | * 36 | * @param DTO $dto 37 | * @return mixed 38 | */ 39 | public function reverseTransform(DTO $dto); 40 | } 41 | -------------------------------------------------------------------------------- /src/Black/DDD/DDDinPHP/Application/DTO/DTO.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Black\DDD\DDDinPHP\Application\DTO; 13 | 14 | /** 15 | * Interface DTO 16 | * 17 | * Data transfer object (DTO) is an object that carries data between processes. The motivation for its use has to do 18 | * with the fact that communication between processes is usually done resorting to remote interfaces 19 | * (e.g. web services), where each call is an expensive operation. 20 | * 21 | * Because the majority of the cost of each call is related to the round-trip time between the client and the server, 22 | * one way of reducing the number of calls is to use an object (the DTO) that aggregates the data that would have 23 | * been transferred by the several calls, but that is served by one call only. 24 | * 25 | * @see http://en.wikipedia.org/wiki/Data_transfer_object 26 | */ 27 | interface DTO extends \Serializable 28 | { 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/Black/DDD/DDDinPHP/Application/Service/ApplicationService.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Black\DDD\DDDinPHP\Application\Service; 13 | 14 | /** 15 | * Interface ApplicationService 16 | * 17 | * Application Services are the interface used by the outside world, where the outside world can’t communicate via our 18 | * Entity objects, but may have other representations of them. Application Services could map outside messages to 19 | * internal operations and processes, communicating with services in the Domain and Infrastructure layers to provide 20 | * cohesive operations for outside clients. 21 | * 22 | * @see http://lostechies.com/jimmybogard/2008/08/21/services-in-domain-driven-design/ 23 | */ 24 | interface ApplicationService 25 | { 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/Black/DDD/DDDinPHP/Application/Specification/Specification.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Black\DDD\DDDinPHP\Application\Specification; 13 | 14 | /** 15 | * Interface Specification 16 | * 17 | * A specification pattern outlines a business rule that is combinable with other business rules. 18 | * In this pattern, a unit of business logic inherits its functionality from the abstract aggregate 19 | * Composite Specification class. The Composite Specification class has one function called IsSatisfiedBy that returns a 20 | * boolean value. After instantiation, the specification is "chained" with other specifications, 21 | * making new specifications easily maintainable, yet highly customizable business logic. 22 | * Furthermore upon instantiation the business logic may, through method invocation or inversion of control, 23 | * have its state altered in order to become,a delegate of other classes such as a persistence repository. 24 | * 25 | * @see http://en.wikipedia.org/wiki/Specification_pattern 26 | */ 27 | interface Specification 28 | { 29 | public function isSatisfiedBy($object); 30 | } 31 | -------------------------------------------------------------------------------- /src/Black/DDD/DDDinPHP/Domain/Event/DomainEvent.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Black\DDD\DDDinPHP\Domain\Event; 13 | 14 | /** 15 | * Interface DomainEvent 16 | * 17 | * Domain events are similar to messaging-style eventing, with one key difference. 18 | * With true messaging and a service bus, a message is fired and handled to asynchronously. 19 | * With domain events, the response is synchronous. 20 | * 21 | * Using domain events is rather straight forward. 22 | * 23 | * @see http://lostechies.com/jimmybogard/2010/04/08/strengthening-your-domain-domain-events/ 24 | */ 25 | interface DomainEvent 26 | { 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/Black/DDD/DDDinPHP/Domain/Model/Entity.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Black\DDD\DDDinPHP\Domain\Model; 13 | 14 | /** 15 | * Interface Entity 16 | * 17 | * Objects that have a distinct identity that runs through time and different representations. 18 | * You also hear these called "reference objects". 19 | * 20 | * @see http://martinfowler.com/bliki/EvansClassification.html 21 | */ 22 | interface Entity 23 | { 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/Black/DDD/DDDinPHP/Domain/Model/Repository.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Black\DDD\DDDinPHP\Domain\Model; 13 | 14 | /** 15 | * Interface Repository 16 | * 17 | * Mediates between the domain and data mapping layers using a collection-like 18 | * interface for accessing domain objects. 19 | * 20 | * Your concrete implementation must be in Infrastructure layer in Persistence directory 21 | * 22 | * @see http://martinfowler.com/eaaCatalog/repository.html 23 | */ 24 | interface Repository 25 | { 26 | public function findAll(); 27 | 28 | public function find(ValueObject $vo); 29 | 30 | public function add(Entity $entity); 31 | 32 | public function remove(Entity $entity); 33 | } 34 | -------------------------------------------------------------------------------- /src/Black/DDD/DDDinPHP/Domain/Model/ValueObject.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Black\DDD\DDDinPHP\Domain\Model; 13 | 14 | /** 15 | * Interface ValueObject 16 | * 17 | * Objects that matter only has the combination of their attributes. 18 | * Two value objects with the same values for all their attributes are considered equal. 19 | * 20 | * @see http://martinfowler.com/bliki/EvansClassification.html 21 | */ 22 | interface ValueObject 23 | { 24 | /** 25 | * Return the value of the ValueObject. The value *MUST* be immutable 26 | * 27 | * @return mixed 28 | */ 29 | public function getValue(); 30 | } 31 | -------------------------------------------------------------------------------- /src/Black/DDD/DDDinPHP/Infrastructure/Service/InfrastructureService.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Black\DDD\DDDinPHP\Infrastructure\Service; 13 | 14 | /** 15 | * Interface InfrastructureService 16 | * 17 | * These are services that typically talk to external resources and are not part of the primary problem domain. 18 | * The common examples that I see for this are emailing and logging. When trying to categorize an Infrastructure service, 19 | * I think you can ask yourself the following questions: 20 | * 21 | * If I remove this service, will it affect the execution of my domain model? 22 | * If I remove this service, will it affect the execution of my application? 23 | * 24 | * @see http://www.bennadel.com/blog/2385-application-services-vs-infrastructure-services-vs-domain-services.htm 25 | */ 26 | interface InfrastructureService 27 | { 28 | 29 | } 30 | --------------------------------------------------------------------------------