Skip to content

Conditional Properties

Learn how to use SimpleDTO’s 18 conditional attributes to dynamically include or exclude properties.

Conditional properties are properties that are only included in serialization when certain conditions are met:

class UserDTO extends SimpleDTO
{
public function __construct(
public readonly string $name,
#[WhenAuth] // Only when authenticated
public readonly ?string $email = null,
#[WhenCan('view-admin')] // Only with permission
public readonly ?array $adminData = null,
) {}
}

SimpleDTO provides 18 conditional attributes - 9x more than Spatie Data!

Execute custom logic to determine inclusion:

use Event4u\DataHelpers\SimpleDTO\Attributes\WhenCallback;
class UserDTO extends SimpleDTO
{
public function __construct(
public readonly string $name,
#[WhenCallback(fn($value, $dto) => strlen($value) > 0)]
public readonly ?string $bio = null,
#[WhenCallback(fn($value, $dto) => $dto->age >= 18)]
public readonly ?string $driversLicense = null,
) {}
}

Include when property has a specific value:

use Event4u\DataHelpers\SimpleDTO\Attributes\WhenValue;
class ProductDTO extends SimpleDTO
{
public function __construct(
public readonly string $name,
public readonly string $status,
#[WhenValue('status', 'published')]
public readonly ?string $publishedAt = null,
) {}
}

Include based on null check:

use Event4u\DataHelpers\SimpleDTO\Attributes\WhenNull;
use Event4u\DataHelpers\SimpleDTO\Attributes\WhenNotNull;
class UserDTO extends SimpleDTO
{
public function __construct(
public readonly string $name,
#[WhenNotNull]
public readonly ?string $phone = null,
#[WhenNull('deletedAt')]
public readonly ?string $activeStatus = null,
) {}
}

Include based on boolean value:

use Event4u\DataHelpers\SimpleDTO\Attributes\WhenTrue;
use Event4u\DataHelpers\SimpleDTO\Attributes\WhenFalse;
class UserDTO extends SimpleDTO
{
public function __construct(
public readonly string $name,
public readonly bool $isActive,
#[WhenTrue('isActive')]
public readonly ?string $activeMessage = null,
#[WhenFalse('isActive')]
public readonly ?string $inactiveReason = null,
) {}
}

Include when property equals/not equals a value:

use Event4u\DataHelpers\SimpleDTO\Attributes\WhenEquals;
use Event4u\DataHelpers\SimpleDTO\Attributes\WhenNotEquals;
class OrderDTO extends SimpleDTO
{
public function __construct(
public readonly string $status,
#[WhenEquals('status', 'shipped')]
public readonly ?string $trackingNumber = null,
#[WhenNotEquals('status', 'cancelled')]
public readonly ?string $estimatedDelivery = null,
) {}
}

Include when property is in/not in a list:

use Event4u\DataHelpers\SimpleDTO\Attributes\WhenIn;
use Event4u\DataHelpers\SimpleDTO\Attributes\WhenNotIn;
class UserDTO extends SimpleDTO
{
public function __construct(
public readonly string $role,
#[WhenIn('role', ['admin', 'moderator'])]
public readonly ?array $moderationTools = null,
#[WhenNotIn('role', ['guest', 'banned'])]
public readonly ?array $premiumFeatures = null,
) {}
}

Include based on authentication status:

use Event4u\DataHelpers\SimpleDTO\Attributes\WhenAuth;
use Event4u\DataHelpers\SimpleDTO\Attributes\WhenGuest;
class UserDTO extends SimpleDTO
{
public function __construct(
public readonly string $name,
#[WhenAuth]
public readonly ?string $email = null,
#[WhenGuest]
public readonly ?string $registerPrompt = null,
) {}
}

Include based on user permissions:

use Event4u\DataHelpers\SimpleDTO\Attributes\WhenCan;
class PostDTO extends SimpleDTO
{
public function __construct(
public readonly string $title,
#[WhenCan('edit-posts')]
public readonly ?string $editUrl = null,
#[WhenCan('delete-posts')]
public readonly ?string $deleteUrl = null,
) {}
}

Include based on user role:

use Event4u\DataHelpers\SimpleDTO\Attributes\WhenRole;
class DashboardDTO extends SimpleDTO
{
public function __construct(
public readonly string $title,
#[WhenRole('admin')]
public readonly ?array $adminPanel = null,
#[WhenRole(['admin', 'moderator'])]
public readonly ?array $moderationPanel = null,
) {}
}

Include based on Symfony security:

use Event4u\DataHelpers\SimpleDTO\Attributes\WhenGranted;
class UserDTO extends SimpleDTO
{
public function __construct(
public readonly string $name,
#[WhenGranted('ROLE_ADMIN')]
public readonly ?array $adminData = null,
) {}
}

Include based on Symfony role:

use Event4u\DataHelpers\SimpleDTO\Attributes\WhenSymfonyRole;
class DashboardDTO extends SimpleDTO
{
public function __construct(
public readonly string $title,
#[WhenSymfonyRole('ROLE_ADMIN')]
public readonly ?array $adminPanel = null,
) {}
}

Include based on context value:

use Event4u\DataHelpers\SimpleDTO\Attributes\WhenContext;
class ApiResponseDTO extends SimpleDTO
{
public function __construct(
public readonly string $status,
public readonly array $data,
#[WhenContext('debug')]
public readonly ?array $debugInfo = null,
) {}
}
// Use with context
$dto = ApiResponseDTO::fromArray($data)->withContext(['debug' => true]);

Include when context equals a value:

use Event4u\DataHelpers\SimpleDTO\Attributes\WhenContextEquals;
class UserDTO extends SimpleDTO
{
public function __construct(
public readonly string $name,
#[WhenContextEquals('environment', 'development')]
public readonly ?array $debugData = null,
) {}
}

Include when context is in a list:

use Event4u\DataHelpers\SimpleDTO\Attributes\WhenContextIn;
class ApiResponseDTO extends SimpleDTO
{
public function __construct(
public readonly string $status,
#[WhenContextIn('environment', ['development', 'staging'])]
public readonly ?array $debugInfo = null,
) {}
}
AttributeDescriptionExample
WhenCallbackCustom logic#[WhenCallback(fn($v) => $v > 0)]
WhenValueProperty has value#[WhenValue('status', 'active')]
WhenNullProperty is null#[WhenNull('deletedAt')]
WhenNotNullProperty is not null#[WhenNotNull]
WhenTrueProperty is true#[WhenTrue('isActive')]
WhenFalseProperty is false#[WhenFalse('isActive')]
WhenEqualsProperty equals value#[WhenEquals('status', 'done')]
WhenNotEqualsProperty not equals#[WhenNotEquals('status', 'draft')]
WhenInProperty in list#[WhenIn('role', ['admin'])]
WhenNotInProperty not in list#[WhenNotIn('role', ['guest'])]
WhenAuthUser authenticated (Laravel)#[WhenAuth]
WhenGuestUser is guest (Laravel)#[WhenGuest]
WhenCanUser has permission (Laravel)#[WhenCan('edit')]
WhenRoleUser has role (Laravel)#[WhenRole('admin')]
WhenGrantedUser granted (Symfony)#[WhenGranted('ROLE_ADMIN')]
WhenSymfonyRoleUser has role (Symfony)#[WhenSymfonyRole('ROLE_ADMIN')]
WhenContextContext is truthy#[WhenContext('debug')]
WhenContextEqualsContext equals value#[WhenContextEquals('env', 'dev')]
WhenContextInContext in list#[WhenContextIn('env', ['dev'])]
// ✅ Good - specific attribute
#[WhenAuth]
public readonly ?string $email;
// ❌ Bad - generic callback
#[WhenCallback(fn() => auth()->check())]
public readonly ?string $email;
class UserDTO extends SimpleDTO
{
public function __construct(
public readonly string $name,
#[WhenAuth, Lazy]
public readonly ?array $posts = null,
) {}
}

The following working examples demonstrate this feature:

All examples are fully tested and can be run directly.

The functionality is thoroughly tested. Key test files:

Run the tests:

Terminal window
# Run tests
task test:unit -- --filter=Conditional