PHP code example of creativecrafts / laravel-domain-driven-design-lite

1. Go to this page and download the library: Download creativecrafts/laravel-domain-driven-design-lite library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

creativecrafts / laravel-domain-driven-design-lite example snippets


namespace Modules\Planner\Domain\Actions\Trip;

use Modules\Planner\Domain\Contracts\TripRepositoryContract;
use Modules\Planner\Domain\DTO\CreateTripData;

final class CreateTripAction
{
    public function __construct(
        private TripRepositoryContract $repo,
    ) {}

    public function __invoke(CreateTripData $data): string
    {
        // Domain invariants live here
        return $this->repo->create($data);
    }
}

$this->app->bind(
    TripRepositoryContract::class,
    TripRepository::class,
);



namespace Modules\Billing\Domain\Actions;

use Modules\Billing\Domain\Contracts\InvoiceRepositoryContract;
use Modules\Billing\Domain\DTO\CreateInvoiceData;

final class CreateInvoiceAction
{
    public function __construct(private InvoiceRepositoryContract $repository)
    {
    }

    public function execute(CreateInvoiceData $data): string
    {
        return $this->repository->create($data);
    }
}



namespace Modules\Billing\App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

final class StoreInvoiceRequest extends FormRequest
{
    public function rules(): array
    {
        return [
            'title' => ['



namespace Modules\Billing\App\Http\Controllers;

use Illuminate\Http\JsonResponse;
use Modules\Billing\App\Http\Requests\StoreInvoiceRequest;
use Modules\Billing\Domain\Actions\CreateInvoiceAction;
use Modules\Billing\Domain\DTO\CreateInvoiceData;

final class InvoiceController
{
    public function __construct(private CreateInvoiceAction $action)
    {
    }

    public function store(StoreInvoiceRequest $request): JsonResponse
    {
        $data = new CreateInvoiceData(
            $request->string('title')->toString(),
            $request->integer('amount'),
        );

        $id = $this->action->execute($data);

        return response()->json(['id' => $id], 201);
    }
}



use Modules\Billing\Domain\Actions\CreateInvoiceAction;

it('orchestrates the domain action from the controller', function (): void {
    $action = Mockery::mock(CreateInvoiceAction::class);
    $action->shouldReceive('execute')->once()->andReturn('inv_123');
    $this->instance(CreateInvoiceAction::class, $action);

    $response = $this->postJson('/billing/invoices', [
        'title' => 'Pro Plan',
        'amount' => 1200,
    ]);

    $response->assertCreated()->assertJson(['id' => 'inv_123']);
});



namespace Modules\Payments\Domain\DTO;

final class CreatePaymentData
{
    public function __construct(
        public string $reference,
        public int $amount,
    ) {
    }
}



namespace Modules\Payments\Domain\Contracts;

use Modules\Payments\Domain\DTO\CreatePaymentData;

interface PaymentRepositoryContract
{
    public function create(CreatePaymentData $data): string;
}



namespace Modules\Payments\App\Repositories;

use Modules\Payments\App\Models\Payment;
use Modules\Payments\Domain\Contracts\PaymentRepositoryContract;
use Modules\Payments\Domain\DTO\CreatePaymentData;

final class PaymentRepository implements PaymentRepositoryContract
{
    public function create(CreatePaymentData $data): string
    {
        $payment = Payment::query()->create([
            'reference' => $data->reference,
            'amount' => $data->amount,
        ]);

        return (string) $payment->getKey();
    }
}



namespace Modules\Payments\Domain\Actions;

use Modules\Payments\Domain\Contracts\PaymentRepositoryContract;
use Modules\Payments\Domain\DTO\CreatePaymentData;

final class CreatePaymentAction
{
    public function __construct(private PaymentRepositoryContract $repository)
    {
    }

    public function execute(CreatePaymentData $data): string
    {
        return $this->repository->create($data);
    }
}



namespace Modules\Shared\Domain\ValueObjects;

final class TenantId
{
    public function __construct(public string $value)
    {
    }
}



namespace Modules\Tenancy\Domain\Contracts;

use Modules\Shared\Domain\ValueObjects\TenantId;

interface CurrentTenantResolverContract
{
    public function resolve(): TenantId;
}



namespace Modules\Projects\App\Actions;

use Modules\Shared\Domain\ValueObjects\TenantId;
use Modules\Tenancy\Domain\Contracts\CurrentTenantResolverContract;

final class BuildTenantContext
{
    public function __construct(private CurrentTenantResolverContract $resolver)
    {
    }

    public function handle(): TenantId
    {
        return $this->resolver->resolve();
    }
}

$this->app->bind(
    OrderRepositoryContract::class,
    EloquentOrderRepository::class,
);



namespace Modules\Orders\App\Http\Controllers;

use Illuminate\Http\JsonResponse;
use Modules\Orders\App\Http\Requests\StoreOrderRequest;
use Modules\Orders\Domain\Actions\CreateOrderAction;
use Modules\Orders\Domain\DTO\CreateOrderData;

final class OrderController
{
    public function __construct(private CreateOrderAction $action)
    {
    }

    public function store(StoreOrderRequest $request): JsonResponse
    {
        $data = new CreateOrderData(
            $request->integer('customer_id'),
            $request->integer('total'),
        );

        $id = $this->action->execute($data);

        return response()->json(['id' => $id], 201);
    }
}



namespace Modules\Orders\Domain\Actions;

use Modules\Orders\Domain\Contracts\OrderRepositoryContract;
use Modules\Orders\Domain\DTO\CreateOrderData;

final class CreateOrderAction
{
    public function __construct(private OrderRepositoryContract $repository)
    {
    }

    public function execute(CreateOrderData $data): string
    {
        return $this->repository->create($data);
    }
}



declare(strict_types=1);

namespace Modules\Users\Domain\ValueObjects;

use Egulias\EmailValidator\EmailValidator;
use Egulias\EmailValidator\Validation\RFCValidation;
use InvalidArgumentException;

final readonly class Email
{
    public function __construct(private string $value)
    {
        $validator = new EmailValidator();
        if (!$validator->isValid($value, new RFCValidation())) {
            throw new InvalidArgumentException('Invalid email address.');
        }
    }

    public function value(): string
    {
        return $this->value;
    }

    public function __toString(): string
    {
        return $this->value;
    }
}

use Modules\Users\Domain\ValueObjects\Email;

$email = new Email($data->email);



declare(strict_types=1);

use Modules\Users\Domain\ValueObjects\Email;

it('accepts valid email', function (): void {
    $email = new Email('[email protected]');

    expect((string)$email)->toBe('[email protected]');
});

it('rejects invalid email', function (): void {
    new Email('not-an-email');
})->throws(InvalidArgumentException::class);
bash
php artisan vendor:publish --tag=ddd-lite
php artisan vendor:publish --tag=ddd-lite-stubs
bash
php artisan ddd-lite:publish:quality --target=all
bash
php artisan ddd-lite:publish:quality --target=phpstan
php artisan ddd-lite:publish:quality --target=deptrac
php artisan ddd-lite:publish:quality --target=pest-arch
bash
php artisan vendor:publish --tag=ddd-lite-stubs
bash
php artisan ddd-lite:publish:quality --target=deptrac
php artisan ddd-lite:publish:quality --target=phpstan
bash
php artisan ddd-lite:module Planner
bash
php artisan ddd-lite:make:repository Planner Trip
bash
php artisan ddd-lite:bind Planner TripRepositoryContract TripRepository
bash
php artisan ddd-lite:make:controller Planner Trip --resource
php artisan ddd-lite:make:request Planner StoreTrip
bash
php artisan ddd-lite:doctor:domain --config=deptrac.yaml
bash
php artisan ddd-lite:convert Billing \
  --plan-moves \
  --paths=app/Models,app/Http/Controllers,app/Http/Requests \
  --dry-run
bash
php artisan ddd-lite:convert Billing --rollback=55f96156eac4ea63

app/
  Models/
    BillingAccount.php
  Http/
    Controllers/
      Billing/
        BillingAccountController.php
    Requests/
      Billing/
        StoreBillingAccountRequest.php

modules/
  Billing/
    App/
      Http/
        Controllers/
          BillingAccountController.php
        Requests/
          StoreBillingAccountRequest.php
      Models/
        BillingAccount.php
    Domain/
      Actions/
      Contracts/
      DTO/
bash
php artisan ddd-lite:module Invoicing
bash
php artisan ddd-lite:convert Invoicing \
  --plan-moves \
  --paths=app/Models,app/Http/Controllers,app/Http/Requests \
  --dry-run
bash
php artisan ddd-lite:convert Invoicing --report
bash
php artisan ddd-lite:convert Invoicing --rollback=<manifest-id>
bash
php artisan ddd-lite:module Orders
bash
php artisan ddd-lite:init --module=Core --publish=all --ci=show
bash
php artisan ddd-lite:module Planner
bash
php artisan ddd-lite:convert Planner \
  --plan-moves \
  --paths=app/Http/Controllers,app/Models
bash
php artisan ddd-lite:make:repository Planner Trip
bash
php artisan ddd-lite:make:query Planner TripIndexQuery
php artisan ddd-lite:make:query-builder Planner Trip
php artisan ddd-lite:make:aggregator Planner TripIndexAggregator
bash
php artisan ddd-lite:make:controller Planner Trip --resource
bash
php artisan ddd-lite:make:request Planner StoreTrip
bash
php artisan ddd-lite:bind Planner TripRepositoryContract TripRepository
bash
php artisan ddd-lite:manifest:list --module=Planner --type=create --json
bash
php artisan ddd-lite:manifest:show 2025-11-24-13-54-01 --json
bash
php artisan ddd-lite:doctor --module=Planner --json
bash
php artisan ddd-lite:doctor:domain \
  --config=deptrac.app.yaml \
  --bin=vendor/bin/deptrac \
  --json \
  --fail-on=violations
bash
php artisan ddd-lite:doctor-ci --json --fail-on=error
bash
php artisan ddd-lite:stubs:diff --json
bash
php artisan ddd-lite:stubs:sync --mode=missing
bash
php artisan ddd-lite:publish:quality --target=all
bash
# In your app
vendor/bin/phpstan analyse -c phpstan.app.neon
vendor/bin/deptrac --config=deptrac.app.yaml
php artisan test tests/ArchitectureTest.php