PHP code example of event4u / data-helpers

1. Go to this page and download the library: Download event4u/data-helpers 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/ */

    

event4u / data-helpers example snippets


// From this messy API response...
$apiResponse = [
    'data' => [
        'departments' => [
            ['users' => [['email' => '[email protected]'], ['email' => '[email protected]']]],
            ['users' => [['email' => '[email protected]']]],
        ],
    ],
];

// ...to this clean result in a few lines
$accessor = new DataAccessor($apiResponse);
$emails = $accessor->get('data.departments.*.users.*.email');
// ['[email protected]', '[email protected]', '[email protected]']

// ❌ Without Data Helpers
$emails = [];
foreach ($data['departments'] ?? [] as $dept) {
    foreach ($dept['users'] ?? [] as $user) {
        if (isset($user['email'])) {
            $emails[] = $user['email'];
        }
    }
}

// ✅ With Data Helpers
$emails = $accessor->get('departments.*.users.*.email');

// Works everywhere - no framework needed
$dto = UserDto::fromArray(['name' => 'John', 'email' => '[email protected]']);
$json = json_encode($dto);

// 1. Controller Injection - Automatic validation & filling
class UserController extends Controller
{
    public function store(UserDto $dto): JsonResponse
    {
        // $dto is automatically validated and filled from request
        $user = User::create($dto->toArray());
        return response()->json($user, 201);
    }
}

// 2. Eloquent Model Integration
$user = User::find(1);
$dto = UserDto::fromModel($user);  // From Model
$dto->toModel($user);              // To Model

// 3. Laravel-Specific Attributes
class UserProfileDto extends SimpleDto
{
    public function __construct(
        public readonly string $name,

        #[WhenAuth]  // Only when authenticated
        public readonly ?string $email = null,

        #[WhenCan('edit-posts')]  // Only with permission
        public readonly ?string $editUrl = null,

        #[WhenRole('admin')]  // Only for admins
        public readonly ?array $adminPanel = null,
    ) {}
}

// 4. Artisan Commands
php artisan make:dto UserDto
php artisan dto:typescript
php artisan dto:migrate-spatie

// 1. Controller Injection - Automatic validation & filling
class UserController extends AbstractController
{
    #[Route('/users', methods: ['POST'])]
    public function create(UserDto $dto): JsonResponse
    {
        // $dto is automatically validated and filled from request
        $user = new User();
        $dto->toEntity($user);
        $this->entityManager->persist($user);
        $this->entityManager->flush();
        return $this->json($user, 201);
    }
}

// 2. Doctrine Entity Integration
$user = $this->entityManager->find(User::class, 1);
$dto = UserDto::fromEntity($user);  // From Entity
$dto->toEntity($user);              // To Entity

// 3. Symfony-Specific Attributes
class UserProfileDto extends SimpleDto
{
    public function __construct(
        public readonly string $name,

        #[WhenGranted('ROLE_ADMIN')]  // Only with permission
        public readonly ?string $email = null,

        #[WhenSymfonyRole('ROLE_MODERATOR')]  // Only for moderators
        public readonly ?array $moderationPanel = null,
    ) {}
}

// 4. Console Commands
php bin/console make:dto UserDto
php bin/console dto:typescript

$data = [
    'users' => [
        ['name' => 'Alice', 'age' => '30', 'email' => '[email protected]'],
        ['name' => 'Bob', 'age' => '25', 'email' => '[email protected]'],
    ],
];

$accessor = new DataAccessor($data);

// Generic get() - returns mixed
$emails = $accessor->get('users.*.email');
// ['users.0.email' => '[email protected]', 'users.1.email' => '[email protected]']

// Type-safe getters - strict type conversion with nullable return
$name = $accessor->getString('users.0.name');  // 'Alice'
$age = $accessor->getInt('users.0.age');       // 30 (string → int)
$missing = $accessor->getString('users.0.phone');  // null

// Collection getters for wildcards - returns DataCollection instances
$ages = $accessor->getIntCollection('users.*.age');  // DataCollection<int>
$names = $accessor->getStringCollection('users.*.name');  // DataCollection<string>

// Transformation methods - filter, map, reduce directly on DataAccessor
$filtered = $accessor->filter(fn($user) => $user['age'] > 25);  // [['name' => 'Alice', ...]]
$mapped = $accessor->map(fn($user) => $user['name']);  // ['Alice', 'Bob']
$sum = $accessor->reduce(fn($carry, $user) => $carry + $user['age'], 0);  // 55

// first() and last() with optional callback
$firstUser = $accessor->first();  // ['name' => 'Alice', ...]
$lastAdult = $accessor->last(fn($user) => $user['age'] >= 18);

// Lazy evaluation for large datasets
foreach ($accessor->lazyFilter(fn($user) => $user['age'] > 25) as $user) {
    // Process items one at a time without loading all into memory
}

use event4u\DataHelpers\DataCollection;

$collection = DataCollection::make([1, 2, 3, 4, 5]);

// Filter, map, reduce with method chaining (delegates to DataAccessor)
$result = $collection
    ->filter(fn($item) => $item > 2)  // [3, 4, 5]
    ->map(fn($item) => $item * 2)     // [6, 8, 10]
    ->reduce(fn($carry, $item) => $carry + $item, 0);  // 24

// Dot-notation read access (via DataAccessor)
$collection = DataCollection::make([
    ['user' => ['name' => 'Alice', 'age' => 30]],
    ['user' => ['name' => 'Bob', 'age' => 25]],
]);
$name = $collection->get('0.user.name');  // 'Alice'

// Dot-notation write access (via DataMutator) - modifies in-place
$collection
    ->set('0.user.city', 'Berlin')
    ->merge('1.user', ['city' => 'Munich', 'country' => 'Germany'])
    ->transform('0.user.name', fn($name) => strtoupper($name));

// SQL-like filtering (via DataFilter) - returns new DataCollection
$users = DataCollection::make([
    ['name' => 'Alice', 'age' => 30, 'city' => 'Berlin'],
    ['name' => 'Bob', 'age' => 25, 'city' => 'Munich'],
    ['name' => 'Charlie', 'age' => 35, 'city' => 'Berlin'],
]);
$filtered = $users
    ->query()
    ->where('age', '>', 25)
    ->where('city', 'Berlin')
    ->orderBy('age', 'DESC')
    ->get();  // Returns new DataCollection

// Lazy evaluation for large datasets
foreach ($collection->lazyFilter(fn($item) => $item > 2) as $item) {
    // Process items one at a time without loading all into memory
}

$data = ['user' => ['profile' => []]];
DataMutator::make($data)
    ->set('user.profile.name', 'Alice')
    ->merge('user.profile', ['age' => 30]);
// $data is now modified: ['user' => ['profile' => ['name' => 'Alice', 'age' => 30]]]

$products = [
    ['id' => 1, 'name' => 'Laptop', 'category' => 'Electronics', 'price' => 1200],
    ['id' => 2, 'name' => 'Mouse', 'category' => 'Electronics', 'price' => 25],
    ['id' => 3, 'name' => 'Monitor', 'category' => 'Electronics', 'price' => 400],
];

$result = DataFilter::query($products)
    ->where('category', '=', 'Electronics')
    ->where('price', '>', 100)
    ->orderBy('price', 'DESC')
    ->get();
// Result: [Laptop ($1200), Monitor ($400)]
 skip-test
use event4u\DataHelpers\SimpleDto\Attributes\NoCasts;

// Default: Automatic type casting enabled
class ReadmeUserDto extends SimpleDto
{
    public function __construct(
        public readonly string $name,
        public readonly string $email,
        public readonly int $age,
        public readonly AddressDto $address,  // Nested DTO (auto-cast by default)
    ) {}
}

// Automatic type conversion by default
$user = ReadmeUserDto::fromArray([
    'name' => 'John',
    'email' => '[email protected]',
    'age' => '30',  // String "30" → int 30 (automatic)
    'address' => ['city' => 'Berlin'],  // Array → AddressDto (automatic)
]);

// Disable automatic casting for better performance
#[NoCasts]
class StrictUserDto extends SimpleDto
{
    public function __construct(
        public readonly string $name,
        public readonly int $age,  // Must be int, no conversion
        public readonly AddressDto $address,  // Must be AddressDto instance, no conversion
    ) {}
}

// Multi-format serialization
$json = $user->toJson();  // JSON
$xml = $user->toXml();    // XML
$yaml = $user->toYaml();  // YAML
$csv = $user->toCsv();    // CSV

use event4u\DataHelpers\SimpleDto;
use event4u\DataHelpers\SimpleDto\Attributes\HasObject;
use event4u\DataHelpers\SimpleDto\SimpleDtoObjectTrait;

// Plain PHP object
class Product
{
    public int $id;
    public string $name;
    public float $price;
}

// DTO with plain object integration
#[HasObject(Product::class)]
class ProductDto extends SimpleDto
{
    use SimpleDtoObjectTrait;

    public function __construct(
        public readonly int $id,
        public readonly string $name,
        public readonly float $price,
    ) {}
}

// Object → DTO
$product = new Product();
$product->id = 1;
$product->name = 'Laptop';
$product->price = 999.99;
$dto = ProductDto::fromObject($product);

// DTO → Object
$newProduct = $dto->toObject();  // Uses HasObject attribute

class Customer
{
    private int $id;
    private string $name;

    public function getId(): int { return $this->id; }
    public function setId(int $id): void { $this->id = $id; }
    public function getName(): string { return $this->name; }
    public function setName(string $name): void { $this->name = $name; }
}

// fromObject() uses getters, toObject() uses setters
$dto = CustomerDto::fromObject($customer);
$newCustomer = $dto->toObject(Customer::class);

use event4u\DataHelpers\LiteDto;
use event4u\DataHelpers\LiteDto\Attributes\MapFrom;
use event4u\DataHelpers\LiteDto\Attributes\Hidden;

class UserDto extends LiteDto
{
    public function __construct(
        public readonly string $name,

        #[MapFrom('email_address')]
        public readonly string $email,

        #[Hidden]
        public readonly string $password,
    ) {}
}

$user = UserDto::from([
    'name' => 'John',
    'email_address' => '[email protected]',
    'password' => 'secret',
]);

$array = $user->toArray();
// ['name' => 'John', 'email' => '[email protected]']
// password is hidden

$source = [
    'user' => ['name' => 'John Doe', 'email' => '[email protected]'],
    'orders' => [
        ['id' => 1, 'status' => 'shipped', 'total' => 100],
        ['id' => 2, 'status' => 'pending', 'total' => 50],
        ['id' => 3, 'status' => 'shipped', 'total' => 200],
    ],
];

$result = DataMapper::from($source)
    ->template([
        'customer_name' => '{{ user.name }}',
        'customer_email' => '{{ user.email }}',
        'shipped_orders' => [
            'WHERE' => [
                '{{ orders.*.status }}' => 'shipped',
            ],
            'ORDER BY' => [
                '{{ orders.*.total }}' => 'DESC',
            ],
            '*' => [
                'id' => '{{ orders.*.id }}',
                'total' => '{{ orders.*.total }}',
            ],
        ],
    ])
    ->map()
    ->getTarget();

use event4u\DataHelpers\Helpers\MathHelper;
use event4u\DataHelpers\Helpers\EnvHelper;

// Math operations with precision
$result = MathHelper::add('10.5', '20.3', 2);  // 30.8
$average = MathHelper::average([10, 20, 30]);  // 20.0
$sum = MathHelper::sum([5, 10, 15]);  // 30.0

// Environment variable access with type casting
$debug = EnvHelper::boolean('APP_DEBUG', false);
$port = EnvHelper::integer('APP_PORT', 8080);
$timeout = EnvHelper::float('REQUEST_TIMEOUT', 30.0);

// Load template from database (created with drag-and-drop editor)
$template = Mappings::find(3)->template;

$result = DataMapper::from($source)
    ->template($template)
    ->map()
    ->getTarget();

// Automatic relation detection for Eloquent/Doctrine
$company = new Company();
$result = DataMapper::from($jsonData)
    ->target($company)
    ->template([
        'name' => '{{ company.name }}',
        'departments' => [
            '*' => [
                'name' => '{{ company.departments.*.name }}',
                'budget' => '{{ company.departments.*.budget }}',
            ],
        ],
    ])
    ->map()
    ->getTarget();

use Tests\Utils\Docu\TrimStrings;
use Tests\Utils\Docu\LowercaseEmails;
use Tests\Utils\Docu\SkipEmptyValues;

$source = ['name' => '  John  ', 'email' => '[email protected]'];
$mapping = ['name' => '{{ name }}', 'email' => '{{ email }}'];

$result = DataMapper::from($source)
    ->template($mapping)
    ->pipeline([
        new TrimStrings(),
        new LowercaseEmails(),
        new SkipEmptyValues(),
    ])
    ->map()
    ->getTarget();

// $result = ['name' => 'John', 'email' => '[email protected]']

$mapping = [
    'name' => '{{ user.firstName | ucfirst }} {{ user.lastName | ucfirst }}',
    'email' => '{{ user.email | lower | trim }}',
    'role' => '{{ user.role | upper ?? "USER" }}',
];

$result = DataMapper::query()
    ->source('products', $data)
    ->where('category', 'Electronics')
    ->where('price', '>', 100)
    ->orderBy('price', 'DESC')
    ->groupBy('category', ['total' => ['COUNT']])
    ->get();