adityapratamaf/laravel-cleanarchitecture-cqrs

Laravel 12 Clean Architecture + CQRS (API + Blade)

Maintainers

Package info

github.com/adityapratamaf/Laravel-CleanArchitecture-CQRS

Type:project

pkg:composer/adityapratamaf/laravel-cleanarchitecture-cqrs

Statistics

Installs: 1

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.0.0 2026-03-16 14:59 UTC

This package is not auto-updated.

Last update: 2026-03-17 15:16:44 UTC


README

# Laravel Clean Architecture + CQRS Starter Template

Starter template Laravel 12 yang menggunakan **Clean Architecture + CQRS** dengan struktur yang sederhana, scalable, rapi, dan tidak over-engineered.

Template ini dirancang agar bisa digunakan untuk:

* REST API
* Web UI (Blade)
* Proyek menengah sampai terbesar
* Starter untuk microservice atau modular monolith
* Senior laravel architecture template

---

## ✨ Features

* ✅ Laravel 12
* ✅ Clean Architecture
* ✅ CQRS Pattern
* ✅ DTO-based data transfer
* ✅ CommandBus & QueryBus
* ✅ Global API Exception Handler
* ✅ Support **API** dan **Web Blade**
* ✅ Laravel Sanctum Authentication
* ✅ Custom Pagination Helper
* ✅ Custom Crypto Helper
* ✅ Modular folder structure
* ✅ Routes berada di `app/Presentation/Routes`
* ✅ Views berada di `app/Presentation/Views`
* ✅ Contoh module: **User** dan **Product** + migration + seeder
* ✅ Create new module with artisan
* ✅ Ready for Packagist template usage

---

## 📋 Requirements

* PHP `^8.2`
* Composer
* Database (MySQL/PostgreSQL/SQLite)

---

## 🧠 Clean Architecture & CQRS

### 🏛 Clean Architecture

Diperkenalkan oleh **Robert C. Martin (Uncle Bob)**.

Tujuan:

* Memisahkan business logic dari framework
* Meningkatkan testability
* Mengurangi ketergantungan pada database & UI
* Membuat sistem lebih scalable

#### 🔁 Dependency Rule

> Dependensi hanya boleh mengarah ke dalam (ke Domain).

```text
Framework / DB / UI

Infrastructure

Application

Domain (Core Business)
```

Domain:

* Tidak tahu Laravel
* Tidak tahu HTTP
* Tidak tahu database

---

### ⚡ CQRS

Diperkenalkan oleh **Greg Young**.

Memisahkan:

* ✍ Command → Mengubah state
* 📖 Query → Mengambil data

Tujuan:

* Optimasi read & write
* Mengurangi kompleksitas
* Memudahkan scaling

---

## 🚌 CommandBus & QueryBus

Untuk menghindari tight coupling antara Controller dan Handler, digunakan mediator pattern:

* 🚌 CommandBus
* 🚌 QueryBus

### 🚌 CommandBus

Menangani operasi yang **mengubah state**.

Flow:

```text
Controller → Command → CommandBus → Handler → Repository → Database
```

Contoh:

```php
$command = new CreateUserCommand($name, $email, $password);
$this->commandBus->dispatch($command);
```

Karakteristik:

* Fokus pada perubahan data
* Tidak untuk mengambil data kompleks
* 1 Command = 1 Handler

---

### 🚌 QueryBus

Menangani operasi **read-only**.

Flow:

```text
Controller → Query → QueryBus → Handler → Read Model → Response
```

Contoh:

```php
$query = new ListUsersQuery($search, $page, $perPage);
$result = $this->queryBus->ask($query);
```

Karakteristik:

* Tidak mengubah state
* Return DTO / array / pagination
* Terpisah dari write logic

---

## 🔄 Flow CQRS

### ✍ Write Flow

1. Controller menerima request
2. Validasi via FormRequest
3. Membuat Command
4. Dispatch ke CommandBus
5. Handler memanggil Repository
6. Simpan ke database

### 📖 Read Flow

1. Controller menerima request
2. Membuat Query
3. QueryBus ask ke Handler
4. Handler ambil data
5. Return data + meta pagination

---

## 🧠 Architecture Overview

Project ini menggunakan pendekatan **Clean Architecture** dengan pembagian layer berikut:

```text
app
 ├── Domain

 ├── Application
 │   ├── Shared
 │   │   └── Bus
 │   ├── User
 │   │   ├── DTOs
 │   │   ├── Commands
 │   │   └── Queries
 │   └── Product
 │       ├── DTOs
 │       ├── Commands
 │       └── Queries

 ├── Infrastructure
 │   ├── Persistence
 │   │   ├── Eloquent
 │   │   │   ├── Models
 │   │   │   └── Repositories
 │   └── Providers

 ├── Presentation
 │   ├── Http
 │   │   ├── Controllers
 │   │   │   ├── Api
 │   │   │   └── Web
 │   │   ├── Requests
 │   │   └── Resources
 │   ├── Routes
 │   │   ├── api.php
 │   │   └── web.php
 │   └── Views

 └── Support
     └── Helpers

🚀 1) Membuat Project dari Nol

1.1 Create Laravel project

composer create-project laravel/laravel Laravel-CleanArchitecture-CQRS-Starter-Template
cd Laravel-CleanArchitecture-CQRS-Starter-Template

1.2 Setup environment

cp .env.example .env
php artisan key:generate

1.3 Configure database

Edit .env, contoh MySQL:

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=starter_template
DB_USERNAME=root
DB_PASSWORD=

🧱 2) Membuat Struktur Clean Architecture + CQRS

Jalankan perintah berikut untuk membuat folder layer dan module:

mkdir -p app/{Domain,Application,Infrastructure,Presentation,Support}

mkdir -p app/Domain/User/{Entities,Contracts}
mkdir -p app/Domain/Product/{Entities,Contracts}

mkdir -p app/Application/Shared/Bus
mkdir -p app/Application/User/{DTOs,Commands,Queries}
mkdir -p app/Application/User/Commands/{CreateUser,UpdateUser,DeleteUser}
mkdir -p app/Application/User/Queries/{GetUserById,ListUsers}

mkdir -p app/Application/Product/{DTOs,Commands,Queries}
mkdir -p app/Application/Product/Commands/{CreateProduct,UpdateProduct,DeleteProduct}
mkdir -p app/Application/Product/Queries/{GetProductById,ListProducts}

mkdir -p app/Infrastructure/Persistence/Eloquent/{Models,Repositories}
mkdir -p app/Infrastructure/Providers

mkdir -p app/Presentation/Routes
mkdir -p app/Presentation/Views/{users,products}
mkdir -p app/Presentation/Http/{Controllers,Requests,Resources}
mkdir -p app/Presentation/Http/Controllers/{Api,Web}
mkdir -p app/Presentation/Http/Requests/{User,Product}

mkdir -p app/Support/Helpers

🛣️ 3) Routing & Views dari app/Presentation

Template ini tidak menggunakan routes/web.php dan routes/api.php default. Sebagai gantinya:

  • ✅ Routes: app/Presentation/Routes/web.php dan app/Presentation/Routes/api.php
  • ✅ Views: app/Presentation/Views/...

3.1 Load routes dari app/Presentation/Routes

Edit file: app/Providers/RouteServiceProvider.php

Ubah method boot():

public function boot(): void
{
    $this->routes(function () {
        \Illuminate\Support\Facades\Route::middleware('api')
            ->prefix('api')
            ->group(app_path('Presentation/Routes/api.php'));

        \Illuminate\Support\Facades\Route::middleware('web')
            ->group(app_path('Presentation/Routes/web.php'));
    });
}

3.2 Load views dari app/Presentation/Views

Buat provider:

php artisan make:provider PresentationServiceProvider

Isi app/Infrastructure/Providers/PresentationServiceProvider.php:

<?php

namespace App\Infrastructure\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\View;

class PresentationServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        View::addLocation(app_path('Presentation/Views'));
    }
}

Daftarkan di config/app.php pada bagian providers:

App\Infrastructure\Providers\PresentationServiceProvider::class,

🚌 4) CQRS Pattern

Project ini menggunakan Command Query Responsibility Segregation (CQRS).

4.1 Command

Command digunakan untuk operasi yang mengubah data.

Contoh:

CreateUserCommand
UpdateUserCommand
DeleteUserCommand
CreateProductCommand
UpdateProductCommand
DeleteProductCommand

Setiap command akan diproses oleh handler terkait, misalnya:

CreateUserCommandHandler
CreateProductCommandHandler

4.2 Query

Query digunakan untuk operasi membaca data.

Contoh:

ListUsersQuery
GetUserByIdQuery
ListProductsQuery
GetProductByIdQuery

Setiap query akan diproses oleh handler terkait, misalnya:

ListUsersQueryHandler
GetProductByIdQueryHandler

4.3 Convention

Convention yang dipakai:

  • SomeCommand -> SomeCommandHandler
  • SomeQuery -> SomeQueryHandler

📦 5) DTO (Data Transfer Object)

DTO digunakan untuk mentransfer data antar layer tanpa bergantung langsung pada request atau model.

Contoh:

CreateUserDTO
UpdateUserDTO
CreateProductDTO
UpdateProductDTO

DTO membantu menjaga layer Application tetap bersih dari framework dependency.

🔄 6) Command Bus & Query Bus

Command dan Query tidak dipanggil langsung.

Controller akan menggunakan:

  • app/Application/Shared/Bus/CommandBus.php
  • app/Application/Shared/Bus/QueryBus.php

Contoh penggunaan:

$commandBus->dispatch(new CreateUserCommand($dto));

$queryBus->ask(new ListUsersQuery());

CQRS bus pada template ini dibuat sederhana, scalable, dan mudah dipahami.

🧰 7) Helpers (Tools reusable)

Letak helper:

  • app/Support/Helpers/Pagination.php → meta pagination
  • app/Support/Helpers/Crypto.php → encrypt/decrypt string

Helper ini dipakai berulang kali tanpa overengineering.

Contoh helper lain yang bisa dikembangkan:

PaginationLinks
CryptoHelper
ApiResponse

🛡️ 8) API Error Handling

Project ini menggunakan Global Exception Handler untuk API.

Semua error API akan otomatis diformat menjadi struktur yang konsisten.

Contoh server error:

{
  "result": false,
  "code": 500,
  "message": "server error",
  "errors": null
}

Contoh validation error:

{
  "result": false,
  "code": 422,
  "message": "validation error",
  "errors": {
    "email": ["The email field is required"]
  }
}

🌐 9) Kenapa API beda dengan Web?

9.1 Web

Di Web UI, controller biasanya menggunakan try-catch.

Tujuannya:

  • redirect kembali ke halaman sebelumnya
  • mengirim flash message session('error')
  • menampilkan alert di Blade

Contoh:

try {
   $commandBus->dispatch(new CreateProductCommand($dto));
   return redirect('/products')->with('success', 'Product created');
} catch (DomainException $e) {
   return back()->withInput()->with('error', $e->getMessage());
}

Karena web UI perlu memberikan feedback visual ke user.

9.2 API

Pada API, exception tidak perlu ditangkap di controller.

Jika semua exception ditangkap di controller, maka akan menyebabkan:

  • code menjadi repetitif
  • banyak boilerplate
  • response error tidak konsisten

Sebagai gantinya, project ini menggunakan Global Exception Handler.

Controller API cukup fokus pada:

  • menerima request
  • membuat DTO
  • menjalankan command/query
  • mengembalikan response sukses

Contoh:

$p = $commandBus->dispatch(new CreateProductCommand($dto));

return response()->json([
    'id' => $p->id,
    'name' => $p->name
]);

Jika terjadi error, global handler akan otomatis menangani response JSON.

🗃️ 10) Migrations + Seeders

10.1 Migration users & products

Buat migration jika belum ada:

php artisan make:migration create_products_table
# users table biasanya sudah ada di Laravel default

10.2 Seeder users & products

php artisan make:seeder UserSeeder
php artisan make:seeder ProductSeeder

Daftarkan di database/seeders/DatabaseSeeder.php:

public function run(): void
{
    $this->call([
        UserSeeder::class,
        ProductSeeder::class,
    ]);
}

Jalankan migration dan seeder:

php artisan migrate
php artisan db:seed

Atau sekaligus fresh + seed:

php artisan migrate:fresh --seed

▶️ 11) Menjalankan Project

Clear cache dan autoload:

composer dump-autoload
php artisan optimize:clear

Jalankan server:

php artisan serve

🔐 12) Authentication

API authentication menggunakan Laravel Sanctum.

Login endpoint

POST /api/auth/login

Response contoh:

{
  "token_type": "Bearer",
  "token": "xxxxxx"
}

Gunakan token pada header:

Authorization: Bearer TOKEN

🌐 13) Endpoint yang tersedia

13.1 Web (Blade)

👤 Users

  • GET /users
  • GET /users/create
  • POST /users
  • GET /users/{id}
  • GET /users/{id}/edit
  • PUT /users/{id}
  • DELETE /users/{id}

📦 Products

  • GET /products
  • GET /products/create
  • POST /products
  • GET /products/{id}
  • GET /products/{id}/edit
  • PUT /products/{id}
  • DELETE /products/{id}

🔑 Auth

  • GET /login
  • POST /logout

13.2 API (JSON)

Base prefix: /api

👤 Users

Dokumentasi Users API tetap dipertahankan dan tidak dihapus.

  • GET /api/users
  • POST /api/users
  • GET /api/users/{id}
  • PUT /api/users/{id}
  • DELETE /api/users/{id}

📦 Products

  • GET /api/products
  • POST /api/products
  • GET /api/products/{id}
  • PUT /api/products/{id}
  • DELETE /api/products/{id}

🔐 Auth

  • POST /api/auth/login
  • POST /api/auth/logout

Contoh body JSON create product:

{
  "name": "New Product",
  "sku": "SKU-NEW-001",
  "price": 150000,
  "stock": 5,
  "description": "test"
}

📘 14) Dokumentasi API Auth + Products (Sanctum)

Base URL:

http://localhost:8000

Kalau kamu pakai domain lain, tinggal ganti.

Catatan: Dokumentasi Users API di atas tetap berlaku dan tidak dihapus. Bagian ini adalah tambahan dokumentasi untuk Auth dan Products dengan Bearer Token.

14.1 Login (ambil token)

Endpoint

POST /api/auth/login

cURL

curl -X POST "http://localhost:8000/api/auth/login" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "admin@example.com",
    "password": "password123",
    "device_name": "postman"
  }'

Response contoh

{
  "token_type": "Bearer",
  "token": "1|xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}

Simpan nilai token untuk dipakai di request berikutnya.

14.2 Products (pakai Bearer Token)

Bagian ini berlaku jika route products dimasukkan ke group middleware auth:sanctum.

📄 14.2.1 List products

Endpoint
GET /api/products
cURL
curl -X GET "http://localhost:8000/api/products" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer 1|xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

➕ 14.2.2 Create product

Endpoint
POST /api/products
cURL
curl -X POST "http://localhost:8000/api/products" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer 1|xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -d '{
    "name": "New Product",
    "sku": "SKU-N-999",
    "price": 150000,
    "stock": 5,
    "description": "test product"
  }'

🔍 14.2.3 Show product

Endpoint
GET /api/products/{id}
cURL
curl -X GET "http://localhost:8000/api/products/1" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer 1|xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

✏️ 14.2.4 Update product

Endpoint
PUT /api/products/{id}
cURL
curl -X PUT "http://localhost:8000/api/products/1" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer 1|xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -d '{
    "name": "Product A Updated",
    "sku": "SKU-A-001",
    "price": 175000,
    "stock": 30,
    "description": "updated"
  }'

🗑️ 14.2.5 Delete product

Endpoint
DELETE /api/products/{id}
cURL
curl -X DELETE "http://localhost:8000/api/products/1" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer 1|xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

14.3 Logout (revoke token yang sedang dipakai)

Endpoint

POST /api/auth/logout

cURL

curl -X POST "http://localhost:8000/api/auth/logout" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer 1|xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

Response contoh

{ "message": "Logged out" }

🧩 15) Cara Menambah Module Baru (Pattern cepat)

Checklist module baru X:

15.1 Domain

  • app/Domain/X/Entities
  • app/Domain/X/Contracts

15.2 Application

  • DTOs: CreateXDTO, UpdateXDTO, XDTO, PagedXDTO
  • Commands + Handlers: Create/Update/Delete
  • Queries + Handlers: GetById/List

15.3 Infrastructure

  • Eloquent model + repository implementation

15.4 Presentation

  • Requests: Store/Update
  • Controllers: Api + Web
  • Routes: tambah di app/Presentation/Routes/api.php dan web.php
  • Views: tambah di app/Presentation/Views/x

15.5 Bindings

  • bind repository interface → eloquent repository di CQRSServiceProvider

📦 16) Installation

Clone project:

git clone https://github.com/your-repo/Laravel-CleanArchitecture-CQRS-Starter-Template.git

Install dependency:

composer install

Copy env:

cp .env.example .env

Generate key:

php artisan key:generate

Run migration dan seed:

php artisan migrate --seed

Run server:

php artisan serve
## 🧪 17) Menjalankan Unit Test

Project ini sudah siap untuk pengujian menggunakan **PHPUnit / Pest** bawaan Laravel.

### 17.1 Jalankan semua test

```bash
php artisan test

atau:

vendor/bin/phpunit

17.2 Jalankan test tertentu

Contoh menjalankan file test tertentu:

php artisan test tests/Feature/ProductTest.php

Atau berdasarkan nama test:

php artisan test --filter=ProductTest

17.3 Jalankan test dengan environment testing

Pastikan file .env.testing sudah disiapkan.

APP_ENV=testing
APP_KEY=base64:your-app-key
APP_DEBUG=true

DB_CONNECTION=pgsql
DB_HOST=127.0.0.1
DB_PORT=5432
DB_DATABASE=${DB_SECRET_DATABASE}
DB_USERNAME=${DB_SECRET_USERNAME}
DB_PASSWORD=${DB_SECRET_PASSWORD}

Generate key

php artisan key:generate --env=testing

Set secret key Database, Username & Password di terminal

export DB_SECRET_DATABASE=YOUR_NAME_DATABASE_TESTING
export DB_SECRET_USERNAME=YOUR_USERNAME_DATABASE_TESTING
export DB_SECRET_PASSWORD=YOUR_PASSWORD_DATABASE_TESTING

Contoh:

export DB_SECRET_DATABASE=db_project
export DB_SECRET_USERNAME=postgres
export DB_SECRET_PASSWORD=M3lisaMenariDiMenar@

Check key yang di buat

echo $DB_SECRET_DATABASE
echo $DB_SECRET_USERNAME
echo $DB_SECRET_PASSWORD

Lalu jalankan:

php artisan test

Laravel akan otomatis memakai environment testing saat test dijalankan.

17.4 Jalankan test setelah migrate fresh

Jika test membutuhkan database yang bersih, gunakan trait seperti:

use Illuminate\Foundation\Testing\RefreshDatabase;

Contoh:

<?php

namespace Tests\Feature;

use Tests\TestCase;
use Illuminate\Foundation\Testing\RefreshDatabase;

class ProductTest extends TestCase
{
    use RefreshDatabase;

    public function test_can_list_products(): void
    {
        $response = $this->getJson('/api/products');

        $response->assertStatus(200);
    }
}

Trait RefreshDatabase akan membantu me-refresh database untuk setiap test agar data tetap konsisten.

17.5 Menjalankan test dengan coverage

Jika environment PHP kamu sudah mendukung coverage (Xdebug atau PCOV), jalankan:

php artisan test --coverage

Atau:

vendor/bin/phpunit --coverage-text

17.6 Rekomendasi struktur test

Untuk menjaga konsistensi dengan Clean Architecture + CQRS, pengujian bisa dipisah menjadi:

  • tests/Unit → untuk test DTO, helper, service, handler, dan logic kecil
  • tests/Feature → untuk test endpoint API, controller, auth, dan integrasi flow

Contoh:

tests
 ├── Unit
 │   ├── Helpers
 │   ├── DTOs
 │   └── Handlers
 └── Feature
     ├── Auth
     ├── User
     └── Product

17.7 Contoh alur testing yang disarankan

Urutan yang umum dipakai saat development:

composer dump-autoload
php artisan optimize:clear
php artisan test

Kalau ingin memastikan database testing benar-benar bersih:

php artisan config:clear
php artisan test

📦 18) Publishing ke Packagist (Create Project)

Agar orang bisa install template ini dengan nama project custom:

composer create-project vendor/laravel-cleanarchitecture-cqrs-starter-template MyProjectName

18.1 composer.json minimal untuk template

Pastikan di root composer.json:

  • "type": "project"
  • "name": "vendor/laravel-cleanarchitecture-cqrs-starter-template"

Contoh:

{
  "name": "vendor/laravel-cleanarchitecture-cqrs-starter-template",
  "type": "project",
  "description": "Laravel 12 Clean Architecture + CQRS starter template (API + Blade)",
  "license": "MIT",
  "require": {
    "php": "^8.2",
    "laravel/framework": "^12.0"
  },
  "autoload": {
    "psr-4": {
      "App\\": "app/"
    }
  },
  "scripts": {
    "post-create-project-cmd": [
      "@php artisan key:generate --ansi",
      "@php artisan optimize:clear --ansi"
    ]
  }
}

18.2 Steps publish

  1. Push repository ke GitHub
  2. Daftarkan repository ke Packagist
  3. Buat tag release, misalnya v1.0.0
  4. Packagist akan auto update

📝 19) Notes

  • CQRS di template ini simple & scalable: Command/Query selalu punya Handler dan DTO.
  • Tidak menggunakan package CQRS eksternal agar mudah dipahami dan minim dependency.
  • Views & routes sengaja dipindah ke app/Presentation agar konsisten dengan Clean Architecture.
  • Dokumentasi API Users, Auth Login/Logout, dan Products bisa dipakai sebagai dasar testing di Postman atau cURL.
  • Template ini cocok dipakai sebagai base project maupun starter template open source.

📄 20) Artisan Module Generator

make:module adalah custom Artisan command untuk membantu membuat struktur module baru dengan pola:

  • Clean Architecture
  • CQRS
  • DTO
  • API Controller
  • Web Controller
  • Form Request
  • Blade Views

Command ini dibuat untuk mempercepat pembuatan module baru tanpa harus membuat folder dan file satu per satu secara manual.

  • --fields
  • --test
  • --migration
  • atau tanpa opsi sama sekali

🎯 Tujuan

Generator ini membantu membuat struktur dasar module agar konsisten di seluruh project.

Cocok untuk module seperti:

  • Product
  • Category
  • Brand
  • Customer
  • Supplier
  • Order

Generator ini sengaja dibuat tetap sederhana, supaya:

  • mudah dipahami
  • mudah diubah
  • tidak over-engineering
  • tetap scalable untuk project besar

Karena tujuan utama template ini adalah:

  • memberikan fondasi arsitektur yang rapi
  • mempercepat bootstrap module
  • tetap mudah dipahami oleh developer lain
  • menghindari generator yang terlalu pintar tapi sulit dirawat

⚙️ Command

Basic

Membuat module tanpa migration, fields, atau test.

php artisan make:module Product

Generator akan membuat:

Domain
Application
Infrastructure
Presentation

tanpa migration dan test.

🧱 Generate Module + Fields

Jika ingin langsung membuat struktur dengan field entity.

php artisan make:module Product \
--fields="name:string,sku:string,price:decimal,stock:int"

Contoh field yang didukung:

Type Example
string name:string
int stock:int
decimal price:decimal
text description:text
nullable description:text?

Nullable menggunakan tanda ?.

Contoh:

description:text?

🧪 Generate Module + Test

Untuk membuat module sekaligus test:

php artisan make:module Product --test

Generator akan membuat:

tests/
 ├ Feature
 │ ├ Api
 │ │ └ ProductApiTest.php
 │
 │ └ Web
 │   └ ProductWebTest.php
 │
 └ Unit
   └ Product
     └ CreateProductCommandHandlerTest.php

🗄 Generate Module + Migration

Untuk membuat module sekaligus migration:

php artisan make:module Product --migration

File migration akan dibuat di:

database/migrations

Contoh:

create_products_table.php

🚀 Generate Module Lengkap (Recommended)

Module + Fields + Test + Migration:

php artisan make:module Product \
--fields="name:string,sku:string,price:decimal,stock:int" \
--test \
--migration

Ini akan membuat:

Domain
Application
Infrastructure
Presentation
Migration
Feature Test
Unit Test

📁 Struktur yang Dibuat

Contoh struktur setelah generate module Product:

app
 ├ Domain
 │  └ Product
 │     ├ Contracts
 │     │  └ ProductRepository.php
 │     │
 │     └ Entities
 │        └ Product.php
 │
 ├ Application
 │  └ Product
 │     ├ DTOs
 │     ├ Commands
 │     └ Queries
 │
 ├ Infrastructure
 │  └ Persistence
 │     └ Eloquent
 │        ├ Models
 │        └ Repositories
 │
 └ Presentation
    ├ Http
    │ ├ Controllers
    │ │ ├ Api
    │ │ └ Web
    │ │
    │ └ Requests
    │
    ├ Routes
    │  └ products.php
    │
    └ Views
       └ products

🧠 Tips Penggunaan

Gunakan nama module dalam bentuk singular.

Benar:

php artisan make:module Product

Hindari:

php artisan make:module Products

Karena generator akan otomatis membuat bentuk plural untuk:

  • views
  • routes
  • table migration

🔧 Setelah Generate Module

Setelah module dibuat, lakukan langkah berikut.

1️⃣ Tambahkan Binding Repository

Tambahkan binding di CQRSServiceProvider.

use App\Domain\Product\Contracts\ProductRepository;
use App\Infrastructure\Persistence\Eloquent\Repositories\EloquentProductRepository;

$this->app->bind(
    ProductRepository::class,
    EloquentProductRepository::class
);

2️⃣ Tambahkan Routes

Copy route dari:

app/Presentation/Routes/products.php

ke file:

routes/api.php

atau

routes/web.php

3️⃣ Jalankan Migration

Jika menggunakan --migration:

php artisan migrate

4️⃣ Jalankan Test

Jika menggunakan --test:

php artisan test

⚠️ Catatan

Generator ini tidak dimaksudkan menggantikan desain domain.

Gunakan generator sebagai:

  • starter structure
  • bootstrap module
  • template awal

Setelah itu silakan:

  • tambah field
  • tambah business rule
  • tambah validation
  • tambah logic domain

sesuai kebutuhan project.

🧩 Filosofi Template Ini

Template ini dibuat dengan prinsip:

  • Clean Architecture
  • CQRS
  • Explicit DTO
  • Simple Repository Pattern
  • No Magic

Dengan tujuan:

  • mudah dipahami
  • mudah di-scale
  • mudah dirawat
  • tidak over-engineered

📄 21) License

MIT License © 2026 Aditya Pratama Febriono This project is open-sourced software licensed under the MIT license.