PHP code example of neuron-php / dto

1. Go to this page and download the library: Download neuron-php/dto 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/ */

    

neuron-php / dto example snippets


use Neuron\Dto\Factory;

// Create DTO from configuration
$factory = new Factory('user.yaml');
$dto = $factory->create();

// Set values
$dto->username = 'johndoe';
$dto->email = '[email protected]';
$dto->age = 25;

// Validate
if (!$dto->validate()) {
    $errors = $dto->getErrors();
    // Handle validation errors
}

// Export as JSON
echo $dto->getAsJson();

use Neuron\Dto\Factory;

// Load from file
$factory = new Factory('path/to/neuron.yaml');
$dto = $factory->create();

// Set properties
$dto->firstName = 'John';
$dto->email = '[email protected]';
$dto->age = 30;

use Neuron\Dto\Dto;
use Neuron\Dto\Property;

$dto = new Dto();

// Create string property
$username = new Property();
$username->setName('username');
$username->setType('string');
$username->setRequired(true);
$username->addLengthValidator(3, 20);

$dto->addProperty($username);

// Create email property
$email = new Property();
$email->setName('email');
$email->setType('email');
$email->setRequired(true);

$dto->addProperty($email);

// Setting nested properties
$dto->address->street = '123 Main St';
$dto->address->city = 'New York';
$dto->address->state = 'NY';
$dto->address->zipCode = '10001';

// Accessing nested properties
$street = $dto->address->street;
$city = $dto->address->city;

use Neuron\Dto\Factory;

// Create DTO with referenced DTOs
$factory = new Factory('article.yaml');
$dto = $factory->create();

// Set values on the main DTO
$dto->id = '550e8400-e29b-41d4-a716-446655440000';
$dto->title = 'My Article';

// Set values on referenced DTOs
$dto->timestamps->createdAt = '2024-01-01 10:00:00';
$dto->timestamps->updatedAt = '2024-01-02 12:00:00';

$dto->author->id = '550e8400-e29b-41d4-a716-446655440001';
$dto->author->username = 'johndoe';
$dto->author->email = '[email protected]';
$dto->author->firstName = 'John';
$dto->author->lastName = 'Doe';

$dto->shippingAddress->street = '123 Main St';
$dto->shippingAddress->city = 'New York';
$dto->shippingAddress->state = 'NY';
$dto->shippingAddress->zipCode = '10001';

// Validate entire structure including referenced DTOs
$dto->validate();

// Export to JSON
echo $dto->getAsJson();

// Validate entire DTO
if( !$dto->validate() ) 
{
    $errors = $dto->getErrors();
    foreach( $errors as $property => $propertyErrors ) 
    {
        echo "Property '$property' has errors:\n";
        foreach( $propertyErrors as $error ) 
        {
            echo "  - $error\n";
        }
    }
}

// Validate specific property
$usernameProperty = $dto->getProperty('username');
if (!$usernameProperty->validate()) {
    $errors = $usernameProperty->getErrors();
}

use Neuron\Validation\IValidator;

class CustomValidator implements IValidator
{
    public function validate($value): bool
    {
        // Custom validation logic
        return $value !== 'forbidden';
    }

    public function getError(): string
    {
        return 'Value cannot be "forbidden"';
    }
}

// Add to property
$property->addValidator(new CustomValidator());

use Neuron\Dto\Mapper\Factory as MapperFactory;

// Create mapper
$mapperFactory = new MapperFactory('mapping.yaml');
$mapper = $mapperFactory->create();

// External data structure
$externalData = [
    'external' => [
        'username' => 'johndoe',
        'user_email' => '[email protected]',
        'user' => [
            'profile' => [
                'age' => 30
            ],
            'contact' => [
                'street' => '123 Main St',
                'city' => 'New York'
            ]
        ],
        'phones' => [
            ['type' => 'mobile', 'value' => '+1234567890'],
            ['type' => 'home', 'value' => '+0987654321']
        ]
    ]
];

// Map to DTO
$mapper->map($dto, $externalData);

// Now DTO contains mapped data
echo $dto->username;  // 'johndoe'
echo $dto->address->street;  // '123 Main St'
echo $dto->phoneNumbers[0]->number;  // '+1234567890'

use Neuron\Dto\Mapper\Dynamic;

$mapper = new Dynamic();

// Define mappings programmatically
$mapper->addMapping('source.field1', 'target.property1');
$mapper->addMapping('source.nested.field2', 'target.property2');

// Map data
$mapper->map($dto, $sourceData);

// Adding items to collection
$dto->users[] = (object)[
    'id' => 1,
    'name' => 'John Doe',
    'email' => '[email protected]'
];

// Accessing collection items
foreach ($dto->users as $user) {
    echo $user->name;
}

// Collection validation
$collection = new Collection($dto->users);
if (!$collection->validate()) {
    $errors = $collection->getErrors();
}

use Neuron\Dto\Factory;

// Create DTO with image property
$factory = new Factory([
    'profile_pic' => [
        'type' => 'image',
        'imageData;

// Or use data URI format
$dto->profile_pic = 'data:image/jpeg;base64,' . $imageData;

// Validate
$dto->validate();

// Get JSON output (image remains as base64 string)
$json = $dto->getAsJson();

// Create a custom validator with SVG enabled
$imageValidator = new \Neuron\Validation\IsImage(
    [], // allowed MIME types (empty = all)
    null, // max size
    true, // check image data
    true  // ALLOW SVG (security risk!)
);

use Neuron\Dto\Dto;

class UserDto extends Dto
{
    public function __construct()
    {
        parent::__construct();
        $this->loadConfiguration('user.yaml');
    }

    public function getFullName(): string
    {
        return $this->firstName . ' ' . $this->lastName;
    }

    public function isAdult(): bool
    {
        return $this->age >= 18;
    }

    public function toArray(): array
    {
        return [
            'username' => $this->username,
            'email' => $this->email,
            'fullName' => $this->getFullName(),
            'isAdult' => $this->isAdult()
        ];
    }
}

use Neuron\Dto\Factory;

class CachedDtoFactory extends Factory
{
    private static array $cache = [];

    public function create(): Dto
    {
        $cacheKey = md5($this->configPath);

        if (!isset(self::$cache[$cacheKey])) {
            self::$cache[$cacheKey] = parent::create();
        }

        // Return deep clone to prevent shared state
        return clone self::$cache[$cacheKey];
    }
}

use PHPUnit\Framework\TestCase;
use Neuron\Dto\Factory;

class DtoTest extends TestCase
{
    private $dto;

    protected function setUp(): void
    {
        $factory = new Factory('test-dto.yaml');
        $this->dto = $factory->create();
    }

    public function testValidation(): void
    {
        $this->dto->username = 'ab';  // Too short
        $this->dto->email = 'invalid-email';

        $this->assertFalse($this->dto->validate());

        $errors = $this->dto->getErrors();
        $this->assertArrayHasKey('username', $errors);
        $this->assertArrayHasKey('email', $errors);
    }

    public function testValidData(): void
    {
        $this->dto->username = 'johndoe';
        $this->dto->email = '[email protected]';
        $this->dto->age = 25;

        $this->assertTrue($this->dto->validate());
        $this->assertEmpty($this->dto->getErrors());
    }

    public function testNestedObjects(): void
    {
        $this->dto->address->street = '123 Main St';
        $this->dto->address->city = 'New York';

        $this->assertEquals('123 Main St', $this->dto->address->street);
        $this->assertEquals('New York', $this->dto->address->city);
    }

    public function testJsonExport(): void
    {
        $this->dto->username = 'johndoe';
        $this->dto->email = '[email protected]';

        $json = $this->dto->getAsJson();
        $decoded = json_decode($json, true);

        $this->assertEquals('johndoe', $decoded['username']);
        $this->assertEquals('[email protected]', $decoded['email']);
    }
}

class MapperTest extends TestCase
{
    public function testDataMapping(): void
    {
        $factory = new Factory('dto.yaml');
        $dto = $factory->create();

        $mapperFactory = new MapperFactory('mapping.yaml');
        $mapper = $mapperFactory->create();

        $sourceData = [
            'external' => [
                'user_name' => 'johndoe',
                'user_email' => '[email protected]'
            ]
        ];

        $mapper->map($dto, $sourceData);

        $this->assertEquals('johndoe', $dto->username);
        $this->assertEquals('[email protected]', $dto->email);
    }
}

// Always validate before processing
if( !$dto->validate() ) 
{
    // Log errors
    Log::error('DTO validation failed', $dto->getErrors());

    // Return early with error response
    return new ValidationErrorResponse($dto->getErrors());
}

// Process valid data
$result = $service->process($dto);

try 
{
    $dto->username = $input['username'];
    $dto->email = $input['email'];

    if( !$dto->validate() ) 
    {
        throw new ValidationException($dto->getErrors());
    }

    $user = $userService->create($dto);

} 
catch( ValidationException $e ) 
{
    // Handle validation errors
    return response()->json([
        'error' => 'Validation failed',
        'details' => $e->getErrors()
    ], 422);

} 
catch (PropertyNotFound $e) 
{
    // Handle missing property
    return response()->json([
        'error' => 'Invalid property: ' . $e->getMessage()
    ], 400);
}

// Base DTO for common properties
abstract class BaseDto extends Dto
{
    protected function addTimestamps(): void
    {
        $createdAt = new Property();
        $createdAt->setName('createdAt');
        $createdAt->setType('date_time');
        $this->addProperty($createdAt);

        $updatedAt = new Property();
        $updatedAt->setName('updatedAt');
        $updatedAt->setType('date_time');
        $this->addProperty($updatedAt);
    }
}

// Specific DTO extending base
class UserDto extends BaseDto
{
    public function __construct()
    {
        parent::__construct();
        $this->loadConfiguration('user.yaml');
        $this->addTimestamps();
    }
}

// Cache DTO definitions
class DtoCache
{
    private static array $definitions = [];

    public static function getDefinition(string $config): array
    {
        if (!isset(self::$definitions[$config])) {
            self::$definitions[$config] = Yaml::parseFile($config);
        }

        return self::$definitions[$config];
    }
}

// Use lazy loading for nested objects
class LazyDto extends Dto
{
    private array $lazyProperties = [];

    public function __get(string $name)
    {
        if( isset( $this->lazyProperties[ $name ] ) ) 
        {
            // Load only when accessed
            $this->loadProperty($name);
        }

        return parent::__get($name);
    }
}

class ApiController
{
    private Factory $dtoFactory;

    public function createUser(Request $request): Response
    {
        $dto = $this->dtoFactory->create('user');

        // Map request data to DTO
        $mapper = new RequestMapper();
        $mapper->map($dto, $request->all());

        // Validate
        if( !$dto->validate() ) 
        {
            return response()->json([
                'errors' => $dto->getErrors()
            ], 422);
        }

        // Process valid data
        $user = $this->userService->create($dto);

        return response()->json($user, 201);
    }
}

class UserRepository
{
    public function save(UserDto $dto): User
    {
        $user = new User();

        $user->username = $dto->username;
        $user->email = $dto->email;
        $user->profile = json_encode([
            'firstName' => $dto->firstName,
            'lastName' => $dto->lastName,
            'address' => [
                'street' => $dto->address->street,
                'city' => $dto->address->city,
                'state' => $dto->address->state,
                'zipCode' => $dto->address->zipCode
            ]
        ]);

        $user->save();

        return $user;
    }

    public function toDto(User $user): UserDto
    {
        $factory = new Factory('user.yaml');
        $dto = $factory->create();

        $dto->username = $user->username;
        $dto->email = $user->email;

        $profile = json_decode($user->profile, true);
        $dto->firstName = $profile['firstName'];
        $dto->lastName = $profile['lastName'];
        $dto->address->street = $profile['address']['street'];
        $dto->address->city = $profile['address']['city'];

        return $dto;
    }
}
bash
composer 
yaml
dto:
  createdAt:
    type: date_time
    : false