Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

jcord's avatar
Level 4

Domain Driven Design - DTO's, Services etc How would you do this?

Hi All,

I am attempting to use DDD principles in my application, currently the app just uses controllers which are fat and i would like to split logic out for maintainability and re-usability.

Can anyone help me on how i should do the following - we have a page for raising credits, each credit consists of base data plus credit lines (of which there can be one or more).

I have created basic DTOs for the SupplierCreditData along with a DTO for SupplierCreditLineData

namespace Domain\Accounting\DataTransferObjects;

use Akaunting\Money\Currency;
use Carbon\Carbon;
use Spatie\LaravelData\Data;
use Akaunting\Money\Money;
use Spatie\LaravelData\DataCollection;

class SupplierCreditData extends Data
{
    public function __construct(
        public readonly ?int $supplierId,
        public readonly Carbon $date,
        public readonly ?string $reference,
        public readonly ?Currency $currency,
        public readonly ?string $currencyId,
        public readonly ?int $periodId,
        public readonly ?string $comments,
        public ?Money $exchangeRate,
        /**
         * @var SupplierCreditGeneralLedgerData[]|null
         */
        public readonly ?DataCollection $generalLedgerEntries,
        /**
         * @var SupplierCreditLineData[]|null
         */
        public readonly ?DataCollection $supplierCreditLines,
        /**
         * @var TaxAuthorityRateData[]|null
         */
        public readonly ?DataCollection $taxAuthorityRates
    ){

    }

}

namespace Domain\Accounting\DataTransferObjects;

use Akaunting\Money\Money;
use Spatie\LaravelData\Data;

class SupplierCreditLineData extends Data
{

    public function __construct(
        public readonly ?int $grnIndexId,
        public readonly ?int $grnBatchId,
        public readonly ?string $sku,
        public readonly ?string $description,
        public readonly ?int $purchaseOrderDetailId,
        public readonly ?Money $changedPrice,
        public readonly ?float $quantityToCredit,
        public readonly ?string $chartmasterAccountCode,
    ){}
}

My understanding is the request comes in, this is converted to DTOs as above, i am then passing the DTOs into an CreditService class which handles calculations and raising of the credit. Currently the CreditService class has methods such as getTotalAmount() which it loops through the SupplierCreditData->supplierCreditLines and gets the total.

My question is should i pass the DTOs into the service class and use them as they are, or should i implement methods such as addCreditLine() which creates new objects and stores them seperately in the service class and then use these instead of the DTOs.

Or am i doing what i always do and just overthinking! I get there is no right or wrong answer essentially but what would you guys do?

0 likes
2 replies
tisuchi's avatar

@jamie.cordingley One approach could be to use the DTOs as they are and pass them into the CreditService class. The service class can then use the data in the DTOs to perform calculations and raise the credit. This approach is useful if the data in the DTOs is all that is needed to perform the necessary calculations and actions in the service class.

Another approach could be to implement methods such as addCreditLine() in the service class, which creates new objects and stores them separately in the service class. This approach is useful if the service class needs to perform additional actions or calculations on the data that are not represented in the DTOs. For example, if the service class needs to perform some validation or business logic on the data before it can be used to raise a credit.

Ultimately, you should choose the approach that best fits the needs of your application and its requirements. And, in your case you can use DTO's as they are and perform the necessary calculations and actions in the service class and handle validations, business logic separately.

1 like
jcord's avatar
Level 4

@tisuchi Understood, thanks very much for clarification, like i said in my post i often complicate aspects beyond whats required, con of working alone i would suspect.

Appreciate the help

1 like

Please or to participate in this conversation.