Installation
composer require adimeo-data-suite/commons
Core Classes
DataSuite\Commons\DataObject base class for immutable data structures.__get()/__set() magic.toArray()/toJson().with() method).First Use Case
use DataSuite\Commons\DataObject;
class User extends DataObject
{
protected $name;
protected $email;
}
$user = new User(['name' => 'John', 'email' => 'john@example.com']);
echo $user->name; // "John"
echo $user->toJson(); // '{"name":"John","email":"john@example.com"}'
Immutable Data Objects
Use DataObject for domain models where state should not change after creation.
$user = new User(['id' => 1]);
$updated = $user->with(['name' => 'Alice']); // Returns new instance
Nested Data Structures
Support nested DataObject instances for complex hierarchies.
class Address extends DataObject { /* ... */ }
class User extends DataObject {
protected $address;
}
$user = new User(['address' => new Address(['city' => 'Paris'])]);
Predefined Validation
Extend DataObject and override validate() for custom rules.
protected function validate(array $data): void {
if (empty($data['email'])) {
throw new \InvalidArgumentException('Email is required.');
}
}
Mass Assignment Protection
Use $fillable to whitelist allowed properties.
protected $fillable = ['name', 'email']; // Only these can be set
Eloquent Models
Use DataObject for DTOs alongside Eloquent.
$user = User::find(1);
$dto = new UserDto($user->toArray());
API Responses
Convert Eloquent collections to DataObject arrays for consistent API output.
return response()->json(array_map(fn ($user) => new UserDto($user), User::all()));
Form Requests
Validate incoming requests and map to DataObject.
$validated = $request->validate([...]);
$user = new User($validated);
JSON/Array Conversion
Leverage toArray()/toJson() for seamless API/DB interactions.
$json = $user->toJson();
$array = json_decode($json, true);
Hydration from External Sources
$data = json_decode(file_get_contents('data.json'), true);
$user = new User($data);
Immutability Overhead
with() creates a new instance. Use sparingly for performance-critical paths.Magic Methods Quirks
__get()/__set() bypass type safety. Ensure properties are properly typed in child classes.@property annotations for IDE support.
/** @property string $name */
Validation Timing
try-catch for graceful handling:
try {
$user = new User($request->all());
} catch (\InvalidArgumentException $e) {
return response()->json(['error' => $e->getMessage()], 400);
}
Circular References
DataObjects with circular references (e.g., User->address->user) will cause infinite recursion in toArray().__toArray() in child classes to handle cycles:
public function __toArray(): array {
return [
'city' => $this->city,
// Exclude 'user' to break the cycle
];
}
Enable Strict Typing
Add declare(strict_types=1); to child classes to catch type mismatches early.
Log DataObject Contents
Override __toString() for debugging:
public function __toString(): string {
return $this->toJson();
}
Custom Serialization
Override toArray() for tailored output:
public function toArray(): array {
return ['full_name' => "{$this->first} {$this->last}"];
}
Dynamic Properties
Use offsetGet()/offsetSet() for dynamic keys (less type-safe):
public function offsetGet($offset) { /* ... */ }
public function offsetSet($offset, $value) { /* ... */ }
Event Dispatching Trigger events on instantiation/modification:
public function __construct(array $data) {
parent::__construct($data);
event(new UserCreated($this));
}
Avoid Deep Cloning
with() creates a shallow copy by default. For large objects, optimize by:
$updated = clone $user;
$updated->name = 'Alice'; // Manual mutation (not immutable)
Batch Processing
Use array_map() with DataObject::fromArray() for bulk conversion:
$users = array_map([User::class, 'fromArray'], $rawData);
How can I help you explore Laravel packages today?