Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/dietrichm/laravel-shopping-api
Laravel 6 based POC for a shopping cart API using DDD and event sourcing.
https://github.com/dietrichm/laravel-shopping-api
ddd demo domain-driven-design event-sourcing laravel laravel6 php poc shop shopping-cart
Last synced: 3 months ago
JSON representation
Laravel 6 based POC for a shopping cart API using DDD and event sourcing.
- Host: GitHub
- URL: https://github.com/dietrichm/laravel-shopping-api
- Owner: dietrichm
- License: agpl-3.0
- Archived: true
- Created: 2020-05-22T11:23:09.000Z (over 4 years ago)
- Default Branch: master
- Last Pushed: 2022-05-05T09:46:22.000Z (over 2 years ago)
- Last Synced: 2024-09-19T16:13:18.756Z (4 months ago)
- Topics: ddd, demo, domain-driven-design, event-sourcing, laravel, laravel6, php, poc, shop, shopping-cart
- Language: PHP
- Homepage:
- Size: 971 KB
- Stars: 5
- Watchers: 2
- Forks: 2
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Laravel Shopping API
![PHP](https://github.com/dietrichm/laravel-shopping-api/workflows/PHP/badge.svg) ![Laravel](https://github.com/dietrichm/laravel-shopping-api/workflows/Laravel/badge.svg)
This project is a POC for the back-end of an online shopping platform. Based on Laravel 6, it implements a small API offering REST endpoints to retrieve product data and create, read, update and checkout orders.
**Note:** lacking some essential auxiliary functionality such as sessions, this project is not suitable for use in a production environment.
- [Technical approach](#technical-approach)
- [Domain-Driven Design (DDD)](#domain-driven-design-ddd)
- [Event sourcing](#event-sourcing)
- [Additional notes and thoughts (05/2022)](#additional-notes-and-thoughts-052022)
- [Installation](#installation)
- [Running tests](#running-tests)
- [Working with the API](#working-with-the-api)
- [License](#license)## Technical approach
The shopping back-end is built using PHP 7 on Laravel 6 and uses Domain-Driven Design inspired patterns and approaches.
Taken from DDD, the domain layer (containing all the business logic, commands and events) is kept separated as much as possible from the application and infrastructural layers.[Please read some notes and thoughts I wrote in hindsight](#additional-notes-and-thoughts-052022).
### Domain-Driven Design (DDD)
The domain layer resides in `domain/` and contains domain objects for _Products_ and _Orders_. It makes use extensively of value objects to represent properties of entities, implements commands and handlers for business scenarios, adds events that can take care of side effects and provides specific domain exceptions. The `Order` entity is an aggregate containing a collection of `LineItem` instances, each holding a reference to the `Product` being added.
While the project strives to have a clean separation between domain and application logic, it still uses Laravel and its base functionality, including Eloquent models, so a pure split-up does not take place. For instance, the `Product` entity is an Eloquent model containing scalar properties as opposed to value objects, and exposes the query builder methods it uses in the domain and application layer. The `Order` entity, on the other hand, is an aggregate root and firmly tied to the implementation offered by the event sourcing package. So, at this point in time, no separate repositories were implemented.
### Event sourcing
We want to keep track of which items were added but also removed from the basket. Both adding as well as removing an item from an order are business commands in the domain layer, each having their proper event.
The shopping platform makes use of event sourcing and persists all Order domain events in the `Order` aggregate root. Recording a new event updates the current state of the aggregate while loading an `Order` from the database replays all domain events that have happened on it, meticulously recreating the state of the `Order` as it was when it was persisted. In particular, removed line items are being collected on the `Order` separately, so they can still be returned from the API in a distinct array in the order JSON data.
Using event sourcing, at every point in time the application knows _exactly_ how the current state was achieved, and can make future decisions based on past actions, such as applying discounts for removed line items.
### Additional notes and thoughts (05/2022)
This project should **not** be considered to represent _the_ way to do DDD or event sourcing with Laravel.
When I built this POC, I found this to be a possible way to move closer to DDD practices and patterns while still operating within the Laravel framework.
Today, I would rather vouch to move even closer to actual DDD patterns, define stricter rules for communication between layers, and use Laravel only in the application layer and for some of the infrastructural parts.As always, your mileage may vary.
## Installation
1. Start the Docker containers by issuing `make`.
This will also build the containers, create an `.env` file and install vendor packages.
1. Run `make artisan key:generate` to generate and add the app key to `.env`.
1. Restart the containers using `make restart`.
This will populate the changes in the environment variables.
1. Create and seed the database tables using `make artisan -- migrate:fresh --seed`.
This will import four demo products which have been provided in a JSON file.
1. Add `0.0.0.0 shopping.test` to your `/etc/hosts` file.## Running tests
The test suite can be run with `make tests`.
## Working with the API
Refer to the [API documentation](docs/api.apib) in an [API Blueprint](https://apiblueprint.org/) file.
## License
Copyright 2020, Dietrich Moerman.
Released under the terms of the [GNU Affero General Public License v3.0](LICENSE).